OSDN Git Service

* fold-const.c (fold_unary_loc): Fold VEC_UNPACK_LO_EXPR,
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Dec 2011 16:41:23 +0000 (16:41 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Dec 2011 16:41:23 +0000 (16:41 +0000)
VEC_UNPACK_HI_EXPR, VEC_UNPACK_FLOAT_LO_EXPR and
VEC_UNPACK_FLOAT_HI_EXPR with VECTOR_CST argument.
(fold_binary_loc): Fold VEC_PACK_TRUNC_EXPR,
VEC_PACK_FIX_TRUNC_EXPR, VEC_WIDEN_MULT_LO_EXPR
and VEC_WIDEN_MULT_HI_EXPR with VECTOR_CST arguments.

* gcc.dg/vect/vect-122.c: New test.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-122.c [new file with mode: 0644]

index 178e222..82031fc 100644 (file)
@@ -1,5 +1,12 @@
 2011-12-03  Jakub Jelinek  <jakub@redhat.com>
 
+       * fold-const.c (fold_unary_loc): Fold VEC_UNPACK_LO_EXPR,
+       VEC_UNPACK_HI_EXPR, VEC_UNPACK_FLOAT_LO_EXPR and
+       VEC_UNPACK_FLOAT_HI_EXPR with VECTOR_CST argument.
+       (fold_binary_loc): Fold VEC_PACK_TRUNC_EXPR,
+       VEC_PACK_FIX_TRUNC_EXPR, VEC_WIDEN_MULT_LO_EXPR
+       and VEC_WIDEN_MULT_HI_EXPR with VECTOR_CST arguments.
+
        PR debug/50317
        * tree-ssa.c (target_for_debug_bind): Also allow is_gimple_reg_type
        vars that aren't referenced.
index 8f31a5f..a32ea90 100644 (file)
@@ -7651,6 +7651,8 @@ build_fold_addr_expr_loc (location_t loc, tree t)
   return build_fold_addr_expr_with_type_loc (loc, t, ptrtype);
 }
 
+static bool vec_cst_ctor_to_array (tree, tree *);
+
 /* Fold a unary expression of code CODE and type TYPE with operand
    OP0.  Return the folded expression if folding is successful.
    Otherwise, return NULL_TREE.  */
@@ -8294,6 +8296,44 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
        }
       return NULL_TREE;
 
+    case VEC_UNPACK_LO_EXPR:
+    case VEC_UNPACK_HI_EXPR:
+    case VEC_UNPACK_FLOAT_LO_EXPR:
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+      {
+       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+       tree *elts, vals = NULL_TREE;
+       enum tree_code subcode;
+
+       gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2);
+       if (TREE_CODE (arg0) != VECTOR_CST)
+         return NULL_TREE;
+
+       elts = XALLOCAVEC (tree, nelts * 2);
+       if (!vec_cst_ctor_to_array (arg0, elts))
+         return NULL_TREE;
+
+       if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_UNPACK_LO_EXPR
+                                  || code == VEC_UNPACK_FLOAT_LO_EXPR))
+         elts += nelts;
+
+       if (code == VEC_UNPACK_LO_EXPR || code == VEC_UNPACK_HI_EXPR)
+         subcode = NOP_EXPR;
+       else
+         subcode = FLOAT_EXPR;
+
+       for (i = 0; i < nelts; i++)
+         {
+           elts[i] = fold_convert_const (subcode, TREE_TYPE (type), elts[i]);
+           if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+             return NULL_TREE;
+         }
+
+       for (i = 0; i < nelts; i++)
+         vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
+       return build_vector (type, vals);
+      }
+
     default:
       return NULL_TREE;
     } /* switch (code) */
@@ -13498,6 +13538,73 @@ fold_binary_loc (location_t loc,
        }
       return NULL_TREE;
 
+    case VEC_PACK_TRUNC_EXPR:
+    case VEC_PACK_FIX_TRUNC_EXPR:
+      {
+       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+       tree *elts, vals = NULL_TREE;
+
+       gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts / 2
+                   && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2);
+       if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST)
+         return NULL_TREE;
+
+       elts = XALLOCAVEC (tree, nelts);
+       if (!vec_cst_ctor_to_array (arg0, elts)
+           || !vec_cst_ctor_to_array (arg1, elts + nelts / 2))
+         return NULL_TREE;
+
+       for (i = 0; i < nelts; i++)
+         {
+           elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
+                                         ? NOP_EXPR : FIX_TRUNC_EXPR,
+                                         TREE_TYPE (type), elts[i]);
+           if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+             return NULL_TREE;
+         }
+
+       for (i = 0; i < nelts; i++)
+         vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
+       return build_vector (type, vals);
+      }
+
+    case VEC_WIDEN_MULT_LO_EXPR:
+    case VEC_WIDEN_MULT_HI_EXPR:
+      {
+       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+       tree *elts, vals = NULL_TREE;
+
+       gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2
+                   && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2);
+       if (TREE_CODE (arg0) != VECTOR_CST || TREE_CODE (arg1) != VECTOR_CST)
+         return NULL_TREE;
+
+       elts = XALLOCAVEC (tree, nelts * 4);
+       if (!vec_cst_ctor_to_array (arg0, elts)
+           || !vec_cst_ctor_to_array (arg1, elts + nelts * 2))
+         return NULL_TREE;
+
+       if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_WIDEN_MULT_LO_EXPR))
+         elts += nelts;
+
+       for (i = 0; i < nelts; i++)
+         {
+           elts[i] = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[i]);
+           elts[i + nelts * 2]
+             = fold_convert_const (NOP_EXPR, TREE_TYPE (type),
+                                   elts[i + nelts * 2]);
+           if (elts[i] == NULL_TREE || elts[i + nelts * 2] == NULL_TREE)
+             return NULL_TREE;
+           elts[i] = const_binop (MULT_EXPR, elts[i], elts[i + nelts * 2]);
+           if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+             return NULL_TREE;
+         }
+
+       for (i = 0; i < nelts; i++)
+         vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
+       return build_vector (type, vals);
+      }
+
     default:
       return NULL_TREE;
     } /* switch (code) */
index 3b03cf7..ffe51d3 100644 (file)
@@ -1,3 +1,7 @@
+2011-12-03  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.dg/vect/vect-122.c: New test.
+
 2011-12-03  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/50684
diff --git a/gcc/testsuite/gcc.dg/vect/vect-122.c b/gcc/testsuite/gcc.dg/vect/vect-122.c
new file mode 100644 (file)
index 0000000..4cbdd0f
--- /dev/null
@@ -0,0 +1,59 @@
+#include "tree-vect.h"
+
+#ifndef N
+#define N 64
+#endif
+
+char a[N];
+float b[N];
+long long l[N], m[N];
+
+__attribute__((noinline, noclone)) int
+f1 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    a[i] = i;
+}
+
+__attribute__((noinline, noclone)) int
+f2 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    b[i] = (double) i;
+}
+
+__attribute__((noinline, noclone)) int
+f3 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    l[i] = (long long) i * (i + 7);
+}
+
+__attribute__((noinline, noclone)) int
+f4 (void)
+{
+  int i;
+  for (i = 0; i < N; i++)
+    m[i] = (long long) i * 7;
+}
+
+int
+main ()
+{
+  int i;
+
+  check_vect ();
+  f1 ();
+  f2 ();
+  f3 ();
+  f4 ();
+  for (i = 0; i < N; i++)
+    if (a[i] != i || b[i] != i || l[i] != i * (i + 7LL) || m[i] != i * 7LL)
+      abort ();
+  return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */