Simplify ((A & N) ==/!= CST1) &/| ((A & M) ==/!= CST2)

Message ID CA+=Sn1m=9AAm0=GfSG38Gg5CNVthcHnijeH3Qyqd02a35tstLA@mail.gmail.com
State New
Headers show
Series
  • Simplify ((A & N) ==/!= CST1) &/| ((A & M) ==/!= CST2)
Related show

Commit Message

Andrew Pinski Jan. 4, 2020, 5:59 a.m.
Hi,
  This adds the following two simplifcations to match.pd:

((A & N) == CST1) & ((A & M) == CST2)
if (N&M)&CST1 == (N&M)&CST2, then
   (A&(N|M)) == (CST1|CST2)
else
  false
And
((A & N) != CST1) | ((A & M) != CST2)

if (N&M)&CST1 == (N&M)&CST2, then
   (A&(N|M)) != (CST1|CST2)
else
  true

NOTE it adds a check to make sure N&~CST1 and M&~CST2 are zero; that
is non outside bits are set in CST1/CST2; just to make sure we don't
have an ordering issue when doing the simplification.

I added a testcase for majority of cases I could think of, so there
are a total of 29 testcases include.

NOTE It does not solve the original testcase in the bug report though,
because we need to handle (A&integer_pow2p) !=/== 0 as ((A &
integer_pow2p) ==/!= integer_pow2p) which is not done in this patch.
I will implement that in a follow up patch.  NOTE this is a step
forward to be able to remove the fold_truth_andor_1 and
optimize_bit_field_compare from fold-const.c.

OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.

Thanks,
Andrew Pinski

ChangeLog:
* match.pd (((A & N) ==/!= CST1) &/| ((A & M) ==/!= CST2)): New pattern.

testsuite/ChangeLog:
* gcc.c-torture/execute/cmpandor-1.c: New testcase
* gcc.c-torture/execute/cmpandor-1.h: New file.
* gcc.dg/tree-ssa/eqand-1.c: New testcase.
* gcc.dg/tree-ssa/eqand-2.c: New testcase.
* gcc.dg/tree-ssa/eqand-3.c: New testcase.
* gcc.dg/tree-ssa/eqand-4.c: New testcase.
* gcc.dg/tree-ssa/eqand-5.c: New testcase.
* gcc.dg/tree-ssa/eqand-6.c: New testcase.
* gcc.dg/tree-ssa/eqand-7.c: New testcase.
* gcc.dg/tree-ssa/eqor-1.c: New testcase.
* gcc.dg/tree-ssa/eqor-2.c: New testcase.
* gcc.dg/tree-ssa/eqor-3.c: New testcase.
* gcc.dg/tree-ssa/eqor-4.c: New testcase.
* gcc.dg/tree-ssa/eqor-5.c: New testcase.
* gcc.dg/tree-ssa/eqor-6.c: New testcase.
* gcc.dg/tree-ssa/eqor-7.c: New testcase.
* gcc.dg/tree-ssa/neand-1.c: New testcase.
* gcc.dg/tree-ssa/neand-2.c: New testcase.
* gcc.dg/tree-ssa/neand-3.c: New testcase.
* gcc.dg/tree-ssa/neand-4.c: New testcase.
* gcc.dg/tree-ssa/neand-5.c: New testcase.
* gcc.dg/tree-ssa/neand-6.c: New testcase.
* gcc.dg/tree-ssa/neand-7.c: New testcase.
* gcc.dg/tree-ssa/neor-1.c: New testcase.
* gcc.dg/tree-ssa/neor-2.c: New testcase.
* gcc.dg/tree-ssa/neor-3.c: New testcase.
* gcc.dg/tree-ssa/neor-4.c: New testcase.
* gcc.dg/tree-ssa/neor-5.c: New testcase.
* gcc.dg/tree-ssa/neor-6.c: New testcase.
* gcc.dg/tree-ssa/neor-7.c: New testcase.

Patch

Index: match.pd
===================================================================
--- match.pd	(revision 279865)
+++ match.pd	(working copy)
@@ -807,6 +807,35 @@  (define_operator_list COND_TERNARY
 	&& TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
     (cmp (bit_and @0 (convert @1)) @2))))
 
+/* Transform ((A & N) ==/!= CST1) &/| ((A & M) ==/!= CST2)
+   if (CST1&~N) == 0 && (CST2&~M) == 0 then
+       if  (N&M)&CST1 != (N&M)&CST2 then
+           false/true
+       else
+           (A&(N|M)) ==/!= (CST1|CST2) */
+(for bitop (bit_and bit_ior)
+     cmp   (eq      ne)
+ (simplify
+  (bitop
+   (cmp (bit_and @0 INTEGER_CST@mask1) INTEGER_CST@CST1)
+   (cmp (bit_and @0 INTEGER_CST@mask2) INTEGER_CST@CST2))
+  (with
+   {
+     tree type1 = TREE_TYPE (@0);
+     wide_int mask1 = wi::to_wide (@mask1);
+     wide_int mask2 = wi::to_wide (@mask2);
+     wide_int newmask = mask1 | mask2;
+     wide_int m = mask1 & mask2;
+     wide_int cst1 = wi::to_wide (@CST1);
+     wide_int cst2 = wi::to_wide (@CST2);
+   }
+   (if (wi::bit_and_not (cst1, mask1) == 0
+        && wi::bit_and_not (cst2, mask2) == 0)
+    (if (wi::eq_p (m & cst1, m & cst2))
+     (cmp (bit_and @0 { wide_int_to_tree (type1, newmask); } )
+          { wide_int_to_tree (type1, cst1 | cst2); } )
+     { constant_boolean_node (cmp == NE_EXPR, type); })))))
+
 /* Fold (A & ~B) - (A & B) into (A ^ B) - B.  */
 (simplify
  (minus (bit_and:cs @0 (bit_not @1)) (bit_and:cs @0 @1))
Index: testsuite/gcc.c-torture/execute/cmpandor-1.c
===================================================================
--- testsuite/gcc.c-torture/execute/cmpandor-1.c	(nonexistent)
+++ testsuite/gcc.c-torture/execute/cmpandor-1.c	(working copy)
@@ -0,0 +1,91 @@ 
+
+#define NOIPA __attribute__((__noipa__))
+
+
+#define functiondefine(name, cmp, bitop, v1, v1cmp, v2, v2cmp)	\
+int name(int a) NOIPA;					\
+int name(int a)						\
+{							\
+  int b = (a & (v1)) cmp (v1cmp);			\
+  int c = (a & (v2)) cmp (v2cmp);			\
+  return b bitop c;					\
+}
+
+
+#define func functiondefine
+#include "cmpandor-1.h"
+#undef func
+
+struct inputsuse
+{
+  const char *name;
+  int (*function)(int);
+  int input;
+  int result;	
+};
+
+#define strivify(input) #input
+
+#define func(name, cmp, bitop, v1, v1cmp, v2, v2cmp) \
+{ \
+	"" #name "_" strivify(input), \
+	&name, \
+	input, \
+	((input) & (v1)) cmp (v1cmp) bitop ((input) & (v2)) cmp (v2cmp) \
+},
+
+struct inputsuse values[] =
+{
+#define input 0
+#include "cmpandor-1.h"
+#undef input
+
+#define input 1
+#include "cmpandor-1.h"
+#undef input
+
+#define input 2
+#include "cmpandor-1.h"
+#undef input
+
+#define input 3
+#include "cmpandor-1.h"
+#undef input
+
+#define input 4
+#include "cmpandor-1.h"
+#undef input
+
+#define input 5
+#include "cmpandor-1.h"
+#undef input
+
+#define input 7
+#include "cmpandor-1.h"
+#undef input
+
+#define input 12
+#include "cmpandor-1.h"
+#undef input
+
+#define input 15
+#include "cmpandor-1.h"
+#undef input
+	
+	
+};
+
+#define SIZEOFARRAY(a) (sizeof(a)/sizeof(a[0]))
+
+int
+main (void)
+{
+	for(int i = 0; i < SIZEOFARRAY(values); i++)
+	{
+	  if (values[i].function(values[i].input) != values[i].result)
+		  __builtin_abort ();
+	  
+	}
+
+}
+
Index: testsuite/gcc.c-torture/execute/cmpandor-1.h
===================================================================
--- testsuite/gcc.c-torture/execute/cmpandor-1.h	(nonexistent)
+++ testsuite/gcc.c-torture/execute/cmpandor-1.h	(working copy)
@@ -0,0 +1,60 @@ 
+ // ((a&3) == 3) & ((a&5) == 5) -> (a&7) == 7
+func(eqand1, ==, &, 3, 3, 5, 5) 
+ // ((a&3) == 3) & ((a&12) == 12) -> (a&15) == 15
+func(eqand2, ==, &, 3, 3, 12, 12)
+ // ((a&3) == 0) & ((a&5) == 0) -> (a&7) == 0
+func(eqand3, ==, &, 3, 0, 5, 0)
+ // ((a&3) == 0) & ((a&12) == 0) -> (a&15) == 0
+func(eqand4, ==, &, 3, 0, 12, 0)
+ // ((a&3) == 3) & ((a&5) == 1) -> (a&7) == 3
+func(eqand5, ==, &, 3, 3, 5, 1)
+ // ((a&3) == 3) & ((a&5) == 4) -> false // mismatch of bits set
+func(eqand6, ==, &, 3, 3, 5, 4)
+ // ((a&3) == 4) & ((a&5) == 5) -> false // mismatch of bits set in the cmp first
+func(eqand7, ==, &, 3, 4, 5, 5)
+
+ // ((a&3) == 3) | ((a&5) == 5)
+func(eqor1, ==, |, 3, 3, 5, 5)
+ // ((a&3) == 3) | ((a&12) == 12)
+func(eqor2, ==, |, 3, 3, 12, 12)
+ // ((a&3) == 3) | ((a&5) == 0)
+func(eqor3, ==, |, 3, 0, 5, 0)
+ // ((a&3) == 0) | ((a&12) == 0)
+func(eqor4, ==, |, 3, 0, 12, 0)
+ // ((a&3) == 3) | ((a&5) == 1)
+func(eqor5, ==, |, 3, 3, 5, 1)
+ // ((a&3) == 3) | ((a&5) == 4)
+func(eqor6, ==, |, 3, 3, 5, 4)
+ // ((a&3) == 4) | ((a&5) == 5) -> ((a&5) == 5) // mismatch of bits set in the cmp first
+func(eqor7, ==, |, 3, 4, 5, 5)
+
+ // ((a&3) != 3) | ((a&5) != 5) 
+func(neand1, !=, &, 3, 3, 5, 5)
+ // ((a&3) != 3) & ((a&12) != 12) 
+func(neand2, !=, &, 3, 3, 12, 12)
+ // ((a&3) != 3) & ((a&5) != 0)
+func(neand3, !=, &, 3, 0, 5, 0)
+ // ((a&3) != 0) & ((a&12) != 0) 
+func(neand4, !=, &, 3, 0, 12, 0)
+ // ((a&3) != 3) & ((a&5) != 1) 
+func(neand5, !=, &, 3, 3, 5, 1)
+ // ((a&3) != 3) & ((a&5) != 4) 
+func(neand6, !=, &, 3, 3, 5, 4)
+ // ((a&3) != 4) & ((a&5) != 5) -> ((a&5) != 5) // mismatch of bits set in the cmp first
+func(neand7, !=, &, 3, 4, 5, 5)
+
+ // ((a&3) != 3) | ((a&5) != 5) -> (a&7) != 7
+func(neor1, !=, |, 3, 3, 5, 5)
+ // ((a&3) != 3) | ((a&12) != 12) -> (a&15) != 15
+func(neor2, !=, |, 3, 3, 12, 12)
+ // ((a&3) != 0) | ((a&5) != 0) -> (a&7) != 0
+func(neor3, !=, |, 3, 0, 5, 0)
+ // ((a&3) != 0) | ((a&12) != 0)  -> (a&15) != 0
+func(neor4, !=, |, 3, 0, 12, 0)
+ // ((a&3) != 3) | ((a&5) != 1) -> (a&7) != 3
+func(neor5, !=, |, 3, 3, 5, 1)
+ // ((a&3) != 3) | ((a&5) != 4) -> true // mismatch of bits set
+func(neor6, !=, |, 3, 3, 5, 4)
+// ((a&3) != 4) | ((a&5) != 5) -> true // mismatch of bits set in the cmp first
+func(neor7, !=, |, 3, 4, 5, 5)
+
Index: testsuite/gcc.dg/tree-ssa/eqand-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqand-1.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqand-1.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) & ((a&5) == 5) -> (a&7) == 7
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&5) == 5);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 7" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 5" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqand-2.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqand-2.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqand-2.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) & ((a&12) == 12) -> (a&15) == 15
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&12) == 12);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 15" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 12" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 12" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqand-3.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqand-3.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqand-3.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 0) & ((a&5) == 0) -> (a&7) == 0
+int f(int a)
+{
+	int b = ((a&3) == 0);
+	int c = ((a&5) == 0);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 0" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqand-4.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqand-4.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqand-4.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 0) & ((a&12) == 0) -> (a&15) == 0
+int f(int a)
+{
+	int b = ((a&3) == 0);
+	int c = ((a&12) == 0);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 0" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 12" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqand-5.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqand-5.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqand-5.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) & ((a&5) == 1) -> (a&7) == 3
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&5) == 1);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 1" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqand-6.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqand-6.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqand-6.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) & ((a&5) == 4) -> false // mismatch of bits set
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&5) == 4);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 4" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqand-7.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqand-7.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqand-7.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 4) & ((a&5) == 5) -> false // mismatch of bits set in the cmp first
+int f(int a)
+{
+	int b = ((a&3) == 4);
+	int c = ((a&5) == 5);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 4" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 5" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqor-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqor-1.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqor-1.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) | ((a&5) == 5)
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&5) == 5);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 7" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 5" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqor-2.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqor-2.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqor-2.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) | ((a&12) == 12)
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&12) == 12);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 15" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 12" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 12" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqor-3.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqor-3.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqor-3.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) | ((a&5) == 0)
+int f(int a)
+{
+	int b = ((a&3) == 0);
+	int c = ((a&5) == 0);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 0" 2 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqor-4.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqor-4.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqor-4.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 0) | ((a&12) == 0)
+int f(int a)
+{
+	int b = ((a&3) == 0);
+	int c = ((a&12) == 0);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 12" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 0" 2 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqor-5.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqor-5.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqor-5.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) | ((a&5) == 1)
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&5) == 1);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 1" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqor-6.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqor-6.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqor-6.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 3) | ((a&5) == 4)
+int f(int a)
+{
+	int b = ((a&3) == 3);
+	int c = ((a&5) == 4);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 0" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 4" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/eqor-7.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/eqor-7.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/eqor-7.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) == 4) | ((a&5) == 5) -> ((a&5) == 5) // mismatch of bits set in the cmp first
+int f(int a)
+{
+	int b = ((a&3) == 4);
+	int c = ((a&5) == 5);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 0" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 4" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 5" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neand-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neand-1.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neand-1.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) | ((a&5) != 5) 
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&5) != 5);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 7" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 5" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neand-2.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neand-2.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neand-2.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) & ((a&12) != 12) 
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&12) != 12);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 15" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 12" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 12" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neand-3.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neand-3.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neand-3.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) & ((a&5) != 0)
+int f(int a)
+{
+	int b = ((a&3) != 0);
+	int c = ((a&5) != 0);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 0" 2 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neand-4.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neand-4.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neand-4.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 0) & ((a&12) != 0) 
+int f(int a)
+{
+	int b = ((a&3) != 0);
+	int c = ((a&12) != 0);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 0" 2 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neand-5.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neand-5.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neand-5.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) & ((a&5) != 1) 
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&5) != 1);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 1" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neand-6.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neand-6.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neand-6.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) & ((a&5) != 4) 
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&5) != 4);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 0" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 4" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neand-7.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neand-7.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neand-7.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 4) & ((a&5) != 5) -> ((a&5) != 5) // mismatch of bits set in the cmp first
+int f(int a)
+{
+	int b = ((a&3) != 4);
+	int c = ((a&5) != 5);
+	return b & c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 0" 0 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 4" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 5" 1 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neor-1.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neor-1.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neor-1.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) | ((a&5) != 5) -> (a&7) != 7
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&5) != 5);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 7" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 5" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neor-2.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neor-2.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neor-2.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) | ((a&12) != 12) -> (a&15) != 15
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&12) != 12);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 15" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 12" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 12" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neor-3.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neor-3.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neor-3.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 0) | ((a&5) != 0) -> (a&7) != 0
+int f(int a)
+{
+	int b = ((a&3) != 0);
+	int c = ((a&5) != 0);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 0" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neor-4.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neor-4.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neor-4.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 0) | ((a&12) != 0)  -> (a&15) != 0
+int f(int a)
+{
+	int b = ((a&3) != 0);
+	int c = ((a&12) != 0);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 15" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 0" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neor-5.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neor-5.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neor-5.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) | ((a&5) != 1) -> (a&7) != 3
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&5) != 1);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "& 7" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 3" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "!= 1" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neor-6.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neor-6.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neor-6.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+ // ((a&3) != 3) | ((a&5) != 4) -> true // mismatch of bits set
+int f(int a)
+{
+	int b = ((a&3) != 3);
+	int c = ((a&5) != 4);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 4" 0 "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/neor-7.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/neor-7.c	(nonexistent)
+++ testsuite/gcc.dg/tree-ssa/neor-7.c	(working copy)
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+
+// ((a&3) != 4) | ((a&5) != 5) -> true // mismatch of bits set in the cmp first
+int f(int a)
+{
+	int b = ((a&3) != 4);
+	int c = ((a&5) != 5);
+	return b | c;
+	
+}
+
+/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
+
+/* { dg-final { scan-tree-dump-times "& 3" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 4" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "& 5" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "== 5" 0 "optimized" } } */