OSDN Git Service

PR middle-end/32912
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Aug 2007 09:22:14 +0000 (09:22 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Aug 2007 09:22:14 +0000 (09:22 +0000)
* fold-const.c (fold_unary): Optimize BIT_NOT_EXPR of VECTOR_CST.
(fold_binary): Handle vectors in X | ~X and X ^ ~X optimizations.

* gcc.dg/pr32912-1.c: New test.
* gcc.dg/pr32912-2.c: New test.
* gcc.dg/pr32912-3.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127661 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr32912-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr32912-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr32912-3.c [new file with mode: 0644]

index aa40fb4..e89bbbc 100644 (file)
@@ -1,3 +1,9 @@
+2007-08-21  Jakub Jelinek  <jakub@redhat.com>
+
+       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  <rguenther@suse.de>
 
        * fold-const.c (fold_binary): Revert removing of index +p PTR folding.
index 33467eb..7718759 100644 (file)
@@ -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);
        }
 
index 9f0b0c8..74321c8 100644 (file)
@@ -1,3 +1,10 @@
+2007-08-21  Jakub Jelinek  <jakub@redhat.com>
+
+       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  <rguenther@suse.de>
 
        * 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 (file)
index 0000000..7526ee1
--- /dev/null
@@ -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 (file)
index 0000000..4254086
--- /dev/null
@@ -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 (file)
index 0000000..e87a32f
--- /dev/null
@@ -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" } } */