https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93131
--- Comment #7 from Andrew Pinski <pinskia at gcc dot gnu.org> --- (In reply to Andrew Pinski from comment #6) > Note the generic version of this is: > ((A & N) == CST1) & ((A & M) == CST2) > > if (N&M)&CST1 == (N&M)&CST2, then > (A&(N|M)) == (CST1|CST2) > else > false And now for the !=/| case: ((A & N) != CST1) | ((A & M) != CST2) if (N&M)&CST1 == (N&M)&CST2, then (A&(N|M)) != (CST1|CST2) else true so something like: (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 mask = wi::to_wide(@mask1) | wi::to_wide(@mask2); wide_int cst1 = wi::to_wide(@cst1); wide_int cst2 = wi::to_wide(@cst2); } (if (wi::eq(mask & cst1,mask & cst2)) (cmp (bit_and @0 {wide_int_to_tree (type1, mask); } ) { wide_int_to_tree (cst1|cst2, mask); } ) { constant_boolean_node (cmp == EQ_EXPR, type); }))))