aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2014-09-12 12:42:47 +0200
committerMarc Glisse <glisse@gcc.gnu.org>2014-09-12 10:42:47 +0000
commitd9a72d17e64f6a1b50ef859dadcf86551de1b265 (patch)
tree27bbde3457695f894291e97fcc17689a975b4a96
parente4a9c55ade081438460f6b0db8afbaad34b05d35 (diff)
downloadgcc-d9a72d17e64f6a1b50ef859dadcf86551de1b265.zip
gcc-d9a72d17e64f6a1b50ef859dadcf86551de1b265.tar.gz
gcc-d9a72d17e64f6a1b50ef859dadcf86551de1b265.tar.bz2
tree.c (integer_each_onep): New function.
2014-09-12 Marc Glisse <marc.glisse@inria.fr> 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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c10
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/vec-andxor1.c17
-rw-r--r--gcc/tree.c15
-rw-r--r--gcc/tree.h5
6 files changed, 55 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index af00004..98586be 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-09-12 Marc Glisse <marc.glisse@inria.fr>
+
+ * 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 <wilco.dijkstra@arm.com>
* gcc/config/aarch64/aarch64.c (cortexa57_regmove_cost): New cost table
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d1b59a1..f7bf525 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 3aba1c7..fb727bf 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2014-09-12 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/vec-andxor1.c: New file.
+
2014-09-11 Marc Glisse <marc.glisse@inria.fr>
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 0000000..4aa454e
--- /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 e40ee23..6ad0575 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 93a940a..93a12d40 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. */