From: Jakub Jelinek Date: Mon, 4 May 2020 08:57:46 +0000 (+0200) Subject: match.pd: Move (X & C) eqne (Y & C) -> -> (X ^ Y) & C eqne 0 opt to match.pd [PR94718] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=73a8043481d24ac86ce8d19459276181dfd9c858;p=gcc.git match.pd: Move (X & C) eqne (Y & C) -> -> (X ^ Y) & C eqne 0 opt to match.pd [PR94718] This patch moves this optimization from fold-const.c to match.pd where it is actually much shorter to do and lets optimize even code not seen together in a single expression in the source, as the first step towards fixing the PR. 2020-05-04 Jakub Jelinek PR tree-optimization/94718 * fold-const.c (fold_binary_loc): Move (X & C) eqne (Y & C) -> (X ^ Y) & C eqne 0 optimization to ... * match.pd ((X & C) op (Y & C) into (X ^ Y) & C op 0): ... here. * gcc.dg/tree-ssa/pr94718-1.c: New test. * gcc.dg/tree-ssa/pr94718-2.c: New test. --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 026ee8b185a..47eef982a59 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2020-05-04 Jakub Jelinek + PR tree-optimization/94718 + * fold-const.c (fold_binary_loc): Move (X & C) eqne (Y & C) + -> (X ^ Y) & C eqne 0 optimization to ... + * match.pd ((X & C) op (Y & C) into (X ^ Y) & C op 0): ... here. + * opts.c (get_option_html_page): Instead of hardcoding a list of options common between C/C++ and Fortran only use gfortran/ documentation for warnings that have CL_Fortran set but not diff --git a/gcc/fold-const.c b/gcc/fold-const.c index b79d059d741..f054871746c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11631,50 +11631,6 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type, return omit_one_operand_loc (loc, type, res, arg0); } - /* Fold (X & C) op (Y & C) as (X ^ Y) & C op 0", and symmetries. */ - if (TREE_CODE (arg0) == BIT_AND_EXPR - && TREE_CODE (arg1) == BIT_AND_EXPR) - { - tree arg00 = TREE_OPERAND (arg0, 0); - tree arg01 = TREE_OPERAND (arg0, 1); - tree arg10 = TREE_OPERAND (arg1, 0); - tree arg11 = TREE_OPERAND (arg1, 1); - tree itype = TREE_TYPE (arg0); - - if (operand_equal_p (arg01, arg11, 0)) - { - tem = fold_convert_loc (loc, itype, arg10); - tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem); - tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg01); - return fold_build2_loc (loc, code, type, tem, - build_zero_cst (itype)); - } - if (operand_equal_p (arg01, arg10, 0)) - { - tem = fold_convert_loc (loc, itype, arg11); - tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem); - tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg01); - return fold_build2_loc (loc, code, type, tem, - build_zero_cst (itype)); - } - if (operand_equal_p (arg00, arg11, 0)) - { - tem = fold_convert_loc (loc, itype, arg10); - tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01, tem); - tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg00); - return fold_build2_loc (loc, code, type, tem, - build_zero_cst (itype)); - } - if (operand_equal_p (arg00, arg10, 0)) - { - tem = fold_convert_loc (loc, itype, arg11); - tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01, tem); - tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg00); - return fold_build2_loc (loc, code, type, tem, - build_zero_cst (itype)); - } - } - if (TREE_CODE (arg0) == BIT_XOR_EXPR && TREE_CODE (arg1) == BIT_XOR_EXPR) { diff --git a/gcc/match.pd b/gcc/match.pd index 9cb37740f1e..123e670f9ee 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4335,7 +4335,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify (cmp (convert? addr@0) integer_zerop) (if (tree_single_nonzero_warnv_p (@0, NULL)) - { constant_boolean_node (cmp == NE_EXPR, type); }))) + { constant_boolean_node (cmp == NE_EXPR, type); })) + + /* (X & C) op (Y & C) into (X ^ Y) & C op 0. */ + (simplify + (cmp (bit_and:cs @0 @2) (bit_and:cs @1 @2)) + (cmp (bit_and (bit_xor @0 @1) @2) { build_zero_cst (TREE_TYPE (@2)); }))) /* If we have (A & C) == C where C is a power of 2, convert this into (A & C) != 0. Similarly for NE_EXPR. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ee5e80e7862..100870acedb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-05-04 Jakub Jelinek + + PR tree-optimization/94718 + * gcc.dg/tree-ssa/pr94718-1.c: New test. + * gcc.dg/tree-ssa/pr94718-2.c: New test. + 2020-05-03 Eric Botcazou * gnat.dg/limited1_inner.adb (Finalize): Use 'Unrestricted_Access. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94718-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94718-1.c new file mode 100644 index 00000000000..510eec815eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94718-1.c @@ -0,0 +1,49 @@ +/* PR tree-optimization/94718 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "= \[xy]_\[0-9]+\\\(D\\\) \\^ \[xy]_\[0-9]+\\\(D\\\);" 6 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[0-9]+ < 0;" 6 "optimized" } } */ + +#define I (-__INT_MAX__ - 1) + +int +f1 (int x, int y) +{ + return (x & I) != (y & I); +} + +int +f2 (int x, int y) +{ + return (~x & I) != (~y & I); +} + +int +f3 (int x, int y) +{ + return ((x & I) ^ I) != ((y & I) ^ I); +} + +int +f4 (int x, int y) +{ + int s = (x & I); + int t = (y & I); + return s != t; +} + +int +f5 (int x, int y) +{ + int s = (~x & I); + int t = (~y & I); + return s != t; +} + +int +f6 (int x, int y) +{ + int s = ((x & I) ^ I); + int t = ((y & I) ^ I); + return s != t; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94718-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94718-2.c new file mode 100644 index 00000000000..15a3d745334 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94718-2.c @@ -0,0 +1,49 @@ +/* PR tree-optimization/94718 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "= \[xy]_\[0-9]+\\\(D\\\) \\^ \[xy]_\[0-9]+\\\(D\\\);" 6 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[0-9]+ >= 0;" 6 "optimized" } } */ + +#define I (-__INT_MAX__ - 1) + +int +f1 (int x, int y) +{ + return (x & I) == (y & I); +} + +int +f2 (int x, int y) +{ + return (~x & I) == (~y & I); +} + +int +f3 (int x, int y) +{ + return ((x & I) ^ I) == ((y & I) ^ I); +} + +int +f4 (int x, int y) +{ + int s = (x & I); + int t = (y & I); + return s == t; +} + +int +f5 (int x, int y) +{ + int s = (~x & I); + int t = (~y & I); + return s == t; +} + +int +f6 (int x, int y) +{ + int s = ((x & I) ^ I); + int t = ((y & I) ^ I); + return s == t; +}