From d9a72d17e64f6a1b50ef859dadcf86551de1b265 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 12 Sep 2014 12:42:47 +0200 Subject: [PATCH] tree.c (integer_each_onep): New function. 2014-09-12 Marc Glisse gcc/ * tree.c (integer_each_onep): New function. * tree.h (integer_each_onep): Declare it. * fold-const.c (fold_binary_loc): Use it for ~A + 1 to -A and -A - 1 to ~A. Disable (X & 1) ^ 1, (X ^ 1) & 1 and ~X & 1 to (X & 1) == 0 for vector and complex. gcc/testsuite/ * gcc.dg/vec-andxor1.c: New file. From-SVN: r215209 --- gcc/ChangeLog | 8 ++++++++ gcc/fold-const.c | 10 ++++++---- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/vec-andxor1.c | 17 +++++++++++++++++ gcc/tree.c | 15 +++++++++++++++ gcc/tree.h | 5 +++++ 6 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vec-andxor1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af000040028..98586be01d1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-09-12 Marc Glisse + + * tree.c (integer_each_onep): New function. + * tree.h (integer_each_onep): Declare it. + * fold-const.c (fold_binary_loc): Use it for ~A + 1 to -A and + -A - 1 to ~A. Disable (X & 1) ^ 1, (X ^ 1) & 1 and ~X & 1 to + (X & 1) == 0 for vector and complex. + 2014-09-12 Wilco Dijkstra * gcc/config/aarch64/aarch64.c (cortexa57_regmove_cost): New cost table diff --git a/gcc/fold-const.c b/gcc/fold-const.c index d1b59a1efd8..f7bf5254e18 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10092,7 +10092,7 @@ fold_binary_loc (location_t loc, { /* Convert ~A + 1 to -A. */ if (TREE_CODE (arg0) == BIT_NOT_EXPR - && integer_onep (arg1)) + && integer_each_onep (arg1)) return fold_build1_loc (loc, NEGATE_EXPR, type, fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0))); @@ -10619,9 +10619,8 @@ fold_binary_loc (location_t loc, fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0))); /* Convert -A - 1 to ~A. */ - if (TREE_CODE (type) != COMPLEX_TYPE - && TREE_CODE (arg0) == NEGATE_EXPR - && integer_onep (arg1) + if (TREE_CODE (arg0) == NEGATE_EXPR + && integer_each_onep (arg1) && !TYPE_OVERFLOW_TRAPS (type)) return fold_build1_loc (loc, BIT_NOT_EXPR, type, fold_convert_loc (loc, type, @@ -11384,6 +11383,7 @@ fold_binary_loc (location_t loc, /* Fold (X & 1) ^ 1 as (X & 1) == 0. */ if (TREE_CODE (arg0) == BIT_AND_EXPR + && INTEGRAL_TYPE_P (type) && integer_onep (TREE_OPERAND (arg0, 1)) && integer_onep (arg1)) return fold_build2_loc (loc, EQ_EXPR, type, arg0, @@ -11494,6 +11494,7 @@ fold_binary_loc (location_t loc, /* Fold (X ^ 1) & 1 as (X & 1) == 0. */ if (TREE_CODE (arg0) == BIT_XOR_EXPR + && INTEGRAL_TYPE_P (type) && integer_onep (TREE_OPERAND (arg0, 1)) && integer_onep (arg1)) { @@ -11507,6 +11508,7 @@ fold_binary_loc (location_t loc, } /* Fold ~X & 1 as (X & 1) == 0. */ if (TREE_CODE (arg0) == BIT_NOT_EXPR + && INTEGRAL_TYPE_P (type) && integer_onep (arg1)) { tree tem2; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3aba1c7026a..fb727bf0464 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-09-12 Marc Glisse + + * gcc.dg/vec-andxor1.c: New file. + 2014-09-11 Marc Glisse PR target/58757 diff --git a/gcc/testsuite/gcc.dg/vec-andxor1.c b/gcc/testsuite/gcc.dg/vec-andxor1.c new file mode 100644 index 00000000000..4aa454e663b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vec-andxor1.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +typedef int vec __attribute__((vector_size(4*sizeof(int)))); + +__attribute__((noinline,noclone)) +void f (vec *x) { + *x = (*x & 1) ^ 1; +} + +int main() { + vec x = { 1, 2, 3, 4 }; + f(&x); + if (x[0] != 0 || x[1] != 1) + __builtin_abort(); + return 0; +} diff --git a/gcc/tree.c b/gcc/tree.c index e40ee23e1e3..6ad05756df0 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -2169,6 +2169,21 @@ integer_onep (const_tree expr) } } +/* Return 1 if EXPR is the integer constant one. For complex and vector, + return 1 if every piece is the integer constant one. */ + +int +integer_each_onep (const_tree expr) +{ + STRIP_NOPS (expr); + + if (TREE_CODE (expr) == COMPLEX_CST) + return (integer_onep (TREE_REALPART (expr)) + && integer_onep (TREE_IMAGPART (expr))); + else + return integer_onep (expr); +} + /* Return 1 if EXPR is an integer containing all 1's in as much precision as it contains, or a complex or vector whose subparts are such integers. */ diff --git a/gcc/tree.h b/gcc/tree.h index 93a940aaee0..93a12d40340 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3947,6 +3947,11 @@ extern int integer_zerop (const_tree); extern int integer_onep (const_tree); +/* integer_onep (tree x) is nonzero if X is an integer constant of value 1, or + a vector or complex where each part is 1. */ + +extern int integer_each_onep (const_tree); + /* integer_all_onesp (tree x) is nonzero if X is an integer constant all of whose significant bits are 1. */ -- 2.30.2