diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa40fb4d138..e89bbbcb90b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2007-08-21 Jakub Jelinek + + PR middle-end/32912 + * fold-const.c (fold_unary): Optimize BIT_NOT_EXPR of VECTOR_CST. + (fold_binary): Handle vectors in X | ~X and X ^ ~X optimizations. + 2007-08-21 Richard Guenther * fold-const.c (fold_binary): Revert removing of index +p PTR folding. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 33467eb88f2..77187596d25 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8397,6 +8397,29 @@ fold_unary (enum tree_code code, tree type, tree op0) TREE_OPERAND (arg0, 1))))) return fold_build2 (BIT_XOR_EXPR, type, fold_convert (type, TREE_OPERAND (arg0, 0)), tem); + /* Perform BIT_NOT_EXPR on each element individually. */ + else if (TREE_CODE (arg0) == VECTOR_CST) + { + tree elements = TREE_VECTOR_CST_ELTS (arg0), elem, list = NULL_TREE; + int count = TYPE_VECTOR_SUBPARTS (type), i; + + for (i = 0; i < count; i++) + { + if (elements) + { + elem = TREE_VALUE (elements); + elem = fold_unary (BIT_NOT_EXPR, TREE_TYPE (type), elem); + if (elem == NULL_TREE) + break; + elements = TREE_CHAIN (elements); + } + else + elem = build_int_cst (TREE_TYPE (type), -1); + list = tree_cons (NULL_TREE, elem, list); + } + if (i == count) + return build_vector (type, nreverse (list)); + } return NULL_TREE; @@ -10485,7 +10508,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (TREE_CODE (arg0) == BIT_NOT_EXPR && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)) { - t1 = build_int_cst_type (type, -1); + t1 = fold_convert (type, integer_zero_node); + t1 = fold_unary (BIT_NOT_EXPR, type, t1); return omit_one_operand (type, t1, arg1); } @@ -10493,7 +10517,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (TREE_CODE (arg1) == BIT_NOT_EXPR && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)) { - t1 = build_int_cst_type (type, -1); + t1 = fold_convert (type, integer_zero_node); + t1 = fold_unary (BIT_NOT_EXPR, type, t1); return omit_one_operand (type, t1, arg0); } @@ -10599,7 +10624,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (TREE_CODE (arg0) == BIT_NOT_EXPR && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)) { - t1 = build_int_cst_type (type, -1); + t1 = fold_convert (type, integer_zero_node); + t1 = fold_unary (BIT_NOT_EXPR, type, t1); return omit_one_operand (type, t1, arg1); } @@ -10607,7 +10633,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (TREE_CODE (arg1) == BIT_NOT_EXPR && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)) { - t1 = build_int_cst_type (type, -1); + t1 = fold_convert (type, integer_zero_node); + t1 = fold_unary (BIT_NOT_EXPR, type, t1); return omit_one_operand (type, t1, arg0); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9f0b0c8584d..74321c891d7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2007-08-21 Jakub Jelinek + + PR middle-end/32912 + * gcc.dg/pr32912-1.c: New test. + * gcc.dg/pr32912-2.c: New test. + * gcc.dg/pr32912-3.c: New test. + 2007-08-21 Richard Guenther * gcc.dg/pointer-arith-10.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/pr32912-1.c b/gcc/testsuite/gcc.dg/pr32912-1.c new file mode 100644 index 00000000000..7526ee145aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr32912-1.c @@ -0,0 +1,44 @@ +/* PR middle-end/32912 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (void); + +typedef int __m128i __attribute__ ((__vector_size__ (16))); + +__m128i a, b, c, d, e, f; + +void +foo (__m128i x) +{ + a = x ^ ~x; + b = ~x ^ x; + c = x | ~x; + d = ~x | x; + e = x & ~x; + f = ~x & x; +} + +int +main (void) +{ + union { __m128i v; int i[sizeof (__m128i) / sizeof (int)]; } u; + int i; + + for (i = 0; i < sizeof (u.i) / sizeof (u.i[0]); i++) + u.i[i] = i * 49 - 36; + foo (u.v); +#define check(x, val) \ + u.v = (x); \ + for (i = 0; i < sizeof (u.i) / sizeof (u.i[0]); i++) \ + if (u.i[i] != (val)) \ + abort () + + check (a, ~0); + check (b, ~0); + check (c, ~0); + check (d, ~0); + check (e, 0); + check (f, 0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr32912-2.c b/gcc/testsuite/gcc.dg/pr32912-2.c new file mode 100644 index 00000000000..4254086b05d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr32912-2.c @@ -0,0 +1,45 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (void); + +typedef int __m128i __attribute__ ((__vector_size__ (16))); + +__m128i a, b, c, d, e, f; + +__m128i +foo (void) +{ + __m128i x = { 0x11111111, 0x22222222, 0x44444444 }; + return x; +} + +__m128i +bar (void) +{ + __m128i x = { 0x11111111, 0x22222222, 0x44444444 }; + return ~x; +} + +int +main (void) +{ + union { __m128i v; int i[sizeof (__m128i) / sizeof (int)]; } u, v; + int i; + + u.v = foo (); + v.v = bar (); + for (i = 0; i < sizeof (u.i) / sizeof (u.i[0]); i++) + { + if (u.i[i] != ~v.i[i]) + abort (); + if (i < 3) + { + if (u.i[i] != (0x11111111 << i)) + abort (); + } + else if (u.i[i]) + abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr32912-3.c b/gcc/testsuite/gcc.dg/pr32912-3.c new file mode 100644 index 00000000000..e87a32f6c91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr32912-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef int __m128i __attribute__ ((__vector_size__ (16))); + +__m128i +bar (void) +{ + __m128i x = { 0x11111111, 0x22222222, 0x44444444 }; + return ~x; +} + +/* { dg-final { scan-tree-dump-not "~" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */