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
This commit is contained in:
Marc Glisse 2014-09-12 12:42:47 +02:00 committed by Marc Glisse
parent e4a9c55ade
commit d9a72d17e6
6 changed files with 55 additions and 4 deletions

View File

@ -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> 2014-09-12 Wilco Dijkstra <wilco.dijkstra@arm.com>
* gcc/config/aarch64/aarch64.c (cortexa57_regmove_cost): New cost table * gcc/config/aarch64/aarch64.c (cortexa57_regmove_cost): New cost table

View File

@ -10092,7 +10092,7 @@ fold_binary_loc (location_t loc,
{ {
/* Convert ~A + 1 to -A. */ /* Convert ~A + 1 to -A. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& integer_onep (arg1)) && integer_each_onep (arg1))
return fold_build1_loc (loc, NEGATE_EXPR, type, return fold_build1_loc (loc, NEGATE_EXPR, type,
fold_convert_loc (loc, type, fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0))); TREE_OPERAND (arg0, 0)));
@ -10619,9 +10619,8 @@ fold_binary_loc (location_t loc,
fold_convert_loc (loc, type, fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0))); TREE_OPERAND (arg0, 0)));
/* Convert -A - 1 to ~A. */ /* Convert -A - 1 to ~A. */
if (TREE_CODE (type) != COMPLEX_TYPE if (TREE_CODE (arg0) == NEGATE_EXPR
&& TREE_CODE (arg0) == NEGATE_EXPR && integer_each_onep (arg1)
&& integer_onep (arg1)
&& !TYPE_OVERFLOW_TRAPS (type)) && !TYPE_OVERFLOW_TRAPS (type))
return fold_build1_loc (loc, BIT_NOT_EXPR, type, return fold_build1_loc (loc, BIT_NOT_EXPR, type,
fold_convert_loc (loc, type, fold_convert_loc (loc, type,
@ -11384,6 +11383,7 @@ fold_binary_loc (location_t loc,
/* Fold (X & 1) ^ 1 as (X & 1) == 0. */ /* Fold (X & 1) ^ 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_AND_EXPR if (TREE_CODE (arg0) == BIT_AND_EXPR
&& INTEGRAL_TYPE_P (type)
&& integer_onep (TREE_OPERAND (arg0, 1)) && integer_onep (TREE_OPERAND (arg0, 1))
&& integer_onep (arg1)) && integer_onep (arg1))
return fold_build2_loc (loc, EQ_EXPR, type, arg0, 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. */ /* Fold (X ^ 1) & 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& INTEGRAL_TYPE_P (type)
&& integer_onep (TREE_OPERAND (arg0, 1)) && integer_onep (TREE_OPERAND (arg0, 1))
&& integer_onep (arg1)) && integer_onep (arg1))
{ {
@ -11507,6 +11508,7 @@ fold_binary_loc (location_t loc,
} }
/* Fold ~X & 1 as (X & 1) == 0. */ /* Fold ~X & 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& INTEGRAL_TYPE_P (type)
&& integer_onep (arg1)) && integer_onep (arg1))
{ {
tree tem2; tree tem2;

View File

@ -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> 2014-09-11 Marc Glisse <marc.glisse@inria.fr>
PR target/58757 PR target/58757

View File

@ -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;
}

View File

@ -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 /* 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. */ it contains, or a complex or vector whose subparts are such integers. */

View File

@ -3947,6 +3947,11 @@ extern int integer_zerop (const_tree);
extern int integer_onep (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 /* integer_all_onesp (tree x) is nonzero if X is an integer constant
all of whose significant bits are 1. */ all of whose significant bits are 1. */