Hi, This adds the folding of x & ((~x) | y)) into x & y on the tree level via fold-const.c There is already partly done on the RTL level but it would be a good thing for the tree level also.
OK for 4.8 (yes I know we have not branched yet but I thought I would send it out so I don't forget about it)? Bootstrapped and tested on x86_64-linux-gnu with no regressions. Thanks, Andrew Pinski ChangeLog: * fold-const.c (fold_binary_loc <case BIT_AND_EXPR>): Add folding of x & (~x | y) into x & y. testsuite/ChangeLog: * gcc.dg/tree-ssa/andor-3.c: New testcase.
Index: fold-const.c =================================================================== --- fold-const.c (revision 183228) +++ fold-const.c (working copy) @@ -11378,6 +11378,43 @@ fold_binary_loc (location_t loc, fold_build1_loc (loc, BIT_NOT_EXPR, type, tem), fold_convert_loc (loc, type, arg0)); } + /* Fold X & (~X | Y) as X & Y. */ + if (TREE_CODE (arg1) == BIT_IOR_EXPR + && TREE_CODE (TREE_OPERAND (arg1, 0)) == BIT_NOT_EXPR + && operand_equal_p (arg0, TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)) + { + tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1)); + return fold_build2_loc (loc, BIT_AND_EXPR, type, + fold_convert_loc (loc, type, arg0), tem); + } + /* Fold X & (Y | ~X) as X & Y. */ + if (TREE_CODE (arg1) == BIT_IOR_EXPR + && TREE_CODE (TREE_OPERAND (arg1, 1)) == BIT_NOT_EXPR + && operand_equal_p (arg0, TREE_OPERAND (TREE_OPERAND (arg1, 1), 0), 0)) + { + tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0)); + return fold_build2_loc (loc, BIT_AND_EXPR, type, + fold_convert_loc (loc, type, arg0), tem); + } + /* Fold (~X | Y) & X as X & Y. */ + if (TREE_CODE (arg0) == BIT_IOR_EXPR + && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_NOT_EXPR + && operand_equal_p (arg1, TREE_OPERAND (TREE_OPERAND (arg0, 0), 0), 0)) + { + tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1)); + return fold_build2_loc (loc, BIT_AND_EXPR, type, + fold_convert_loc (loc, type, arg1), tem); + } + /* Fold (Y | ~X) & X as Y & X. */ + if (TREE_CODE (arg0) == BIT_IOR_EXPR + && TREE_CODE (TREE_OPERAND (arg0, 1)) == BIT_NOT_EXPR + && operand_equal_p (arg1, TREE_OPERAND (TREE_OPERAND (arg0, 1), 0), 0)) + { + tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); + return fold_build2_loc (loc, BIT_AND_EXPR, type, + tem, fold_convert_loc (loc, type, arg1)); + } + /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M, ((A & N) + B) & M -> (A + B) & M Index: testsuite/gcc.dg/tree-ssa/andor-3.c =================================================================== --- testsuite/gcc.dg/tree-ssa/andor-3.c (revision 0) +++ testsuite/gcc.dg/tree-ssa/andor-3.c (revision 0) @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +int f(int y, int x) +{ + return x & ((~x) | y); +} +int f1(int y, int x) +{ + return x & (y | (~x)); +} +int f2(int y, int x) +{ + return ((~x) | y) & x; +} +int f3(int y, int x) +{ + return (y | (~x)) & x; +} + + +/* { dg-final { scan-tree-dump-times "~x" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "x \& y" 4 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */