From: Robin Dapp <[email protected]>

Similar to float handling, this patch now adds vector handling.  As the
wrapper is already there, all we need to do is add a few vector special
cases to it.

gcc/ChangeLog:

        * tree-ssa-reassoc.cc (constant_maybe_expensive): Add vector
        handling.
        (struct mult_factor): Add is_vector and vector handling to
        constructor and tree building.
        (linearize_plus_mult_tree): Allow vectors.
        (rewrite_plus_mult_tree): Likewise.
        (reassociate_bb): Likewise.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/reassoc-56.c: New test.
        * gcc.dg/tree-ssa/reassoc-57.c: New test.
---
 gcc/testsuite/gcc.dg/tree-ssa/reassoc-56.c |  53 ++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/reassoc-57.c |  53 ++++++++++
 gcc/tree-ssa-reassoc.cc                    | 107 +++++++++++++++------
 3 files changed, 186 insertions(+), 27 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/reassoc-56.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/reassoc-57.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-56.c 
b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-56.c
new file mode 100644
index 00000000000..9d86aa7d5a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-56.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Signed and unsigned vector reassociation plus/mult-tree rewrite tests.
+   The signed tests are xfailed for now.  */
+
+typedef unsigned int v4ui __attribute__((vector_size (4 * sizeof (unsigned 
int))));
+typedef short v8si __attribute__((vector_size (8 * sizeof (short))));
+
+v4ui
+bar (v4ui fs)
+{
+  return 3u * (fs + 1u) + 4u * (fs + 2u);
+}
+
+v4ui
+foo1 (v4ui fs)
+{
+  return 2u * (3u * (fs + 1u) + 4u * (fs + 2u));
+}
+
+v4ui
+foo2 (v4ui fs)
+{
+  return 2u * (3u * (2u * (fs + 1u) + 2u * (fs + 2u)) + fs);
+}
+
+v4ui
+foo3 (v4ui fs)
+{
+  v4ui tmp = 3u * (fs + 1u);
+  return fs + 2u * (tmp + 4u) - 3u * (fs + 2u) + 5u + fs;
+}
+
+v8si
+foo (v8si fs)
+{
+  return 2 * (fs + 1) + 4 * (fs + 2);
+}
+
+v8si
+baz (v8si fs)
+{
+  return 16 * (fs + 1) + 64 * (fs + 2);
+}
+
+/* { dg-final { scan-tree-dump-times "\{ 7, 7, 7, 7 \}" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\{ 14, 14, 14, 14 \}" 1 "optimized" } } 
*/
+/* { dg-final { scan-tree-dump-times "\{ 26, 26, 26, 26 \}" 1 "optimized" } } 
*/
+/* { dg-final { scan-tree-dump-times "\{ 5, 5, 5, 5 \}" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\{ 6, 6, 6, 6, 6, 6, 6, 6 \}" 1 
"optimized" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "\{ 80, 80, 80, 80, 80, 80, 80, 80 \}" 1 
"optimized" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-57.c 
b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-57.c
new file mode 100644
index 00000000000..2f280722ce6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-57.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1-details" } */
+
+/* Float vector reassociation plus/mult-tree rewrite tests.  */
+
+typedef float v4sf __attribute__((vector_size (4 * sizeof (float))));
+typedef double v2df __attribute__((vector_size (2 * sizeof (double))));
+
+v4sf
+bar (v4sf fs)
+{
+  return 3u * (fs + 1u) + 4u * (fs + 2u);
+}
+
+v4sf
+foo1 (v4sf fs)
+{
+  return 2u * (3u * (fs + 1u) + 4u * (fs + 2u));
+}
+
+v4sf
+foo2 (v4sf fs)
+{
+  return 2u * (3u * (2u * (fs + 1u) + 2u * (fs + 2u)) + fs);
+}
+
+v4sf
+foo3 (v4sf fs)
+{
+  v4sf tmp = 3u * (fs + 1u);
+  return fs + 2u * (tmp + 4u) - 3u * (fs + 2u) + 5u + fs;
+}
+
+v2df
+foo (v2df fs)
+{
+  return 2 * (fs + 1) + 4 * (fs + 2);
+}
+
+v2df
+baz (v2df fs)
+{
+  return 16 * (fs + 1) + 64 * (fs + 2);
+}
+
+/* { dg-final { scan-tree-dump-times "\{ 7\\.0e\\+0, 7\\.0e\\+0, 7\\.0e\\+0, 
7\\.0e\\+0 \}" 1 "reassoc1" } } */
+/* { dg-final { scan-tree-dump-times "\{ 1\\.4e\\+1, 1\\.4e\\+1, 1\\.4e\\+1, 
1\\.4e\\+1 \}" 1 "reassoc1" } } */
+/* { dg-final { scan-tree-dump-times "\{ 2\\.6e\\+1, 2\\.6e\\+1, 2\\.6e\\+1, 
2\\.6e\\+1 \}" 1 "reassoc1" } } */
+/* { dg-final { scan-tree-dump-times "\{ 5\\.0e\\+0, 5\\.0e\\+0, 5\\.0e\\+0, 
5\\.0e\\+0 \}" 1 "reassoc1" } } */
+/* { dg-final { scan-tree-dump-times "\{ 6\\.0e\\+0, 6\\.0e\\+0 \}" 1 
"reassoc1" } } */
+/* { dg-final { scan-tree-dump-times "\{ 8\\.0e\\+1, 8\\.0e\\+1 \}" 1 
"reassoc1" } } */
diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
index 440c6271e28..54a7be64e54 100644
--- a/gcc/tree-ssa-reassoc.cc
+++ b/gcc/tree-ssa-reassoc.cc
@@ -1860,13 +1860,14 @@ undistribute_ops_list (enum tree_code opcode,
 /* Simplistic function to estimate whether a constant might be expensive to
    materialize.  */
 static inline bool
-constant_maybe_expensive (wide_int cst)
+constant_maybe_expensive (wide_int cst, bool vector = false)
 {
-  return wi::gts_p (wi::abs (cst), 2048) && wi::popcount (cst) > 1;
+  return wi::gts_p (wi::abs (cst), !vector ? 2048: 64)
+    && wi::popcount (cst) > 1;
 }
 
 static inline bool
-constant_maybe_expensive (REAL_VALUE_TYPE)
+constant_maybe_expensive (REAL_VALUE_TYPE, bool = false)
 {
   return false;
 }
@@ -1876,11 +1877,22 @@ constant_maybe_expensive (tree t)
 {
   tree type = TREE_TYPE (t);
   gcc_checking_assert (INTEGRAL_TYPE_P (type)
-                       || SCALAR_FLOAT_TYPE_P (type));
-  if (INTEGRAL_TYPE_P (type))
-    return constant_maybe_expensive (wi::to_wide (t));
+                      || VECTOR_INTEGER_TYPE_P (type)
+                      || FLOAT_TYPE_P (type));
+
+  bool vector_p = false;
+  if (VECTOR_TYPE_P (type))
+    {
+      t = uniform_vector_p (t);
+      vector_p = true;
+    }
+
+  if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+    {
+      return constant_maybe_expensive (wi::to_wide (t), vector_p);
+    }
   else
-    return constant_maybe_expensive (TREE_REAL_CST (t));
+    return constant_maybe_expensive (TREE_REAL_CST (t), vector_p);
 }
 
 /* Helper to wrap operations for the constant multiplicative factors in
@@ -1892,7 +1904,9 @@ struct mult_factor
 
   HOST_WIDE_INT prec;
   tree type;
+
   bool is_float;
+  bool is_vector;
 
   bool is_zero ()
     {
@@ -1905,8 +1919,15 @@ struct mult_factor
   void mul (tree other)
     {
       tree other_type = TREE_TYPE (other);
-      gcc_checking_assert ((!is_float && INTEGRAL_TYPE_P (other_type))
-                          || (is_float && SCALAR_FLOAT_TYPE_P (other_type)));
+      gcc_checking_assert ((!is_float
+                           && (INTEGRAL_TYPE_P (other_type)
+                               || VECTOR_INTEGER_TYPE_P (other_type)))
+                           || (is_float && FLOAT_TYPE_P (other_type)));
+
+      gcc_checking_assert (VECTOR_TYPE_P (type) == VECTOR_TYPE_P (other_type));
+      if (VECTOR_TYPE_P (type))
+       other = uniform_vector_p (other);
+
       if (!is_float)
        cst = wi::mul (cst, wi::to_wide (other));
       else
@@ -1917,6 +1938,7 @@ struct mult_factor
   void mul (mult_factor &other)
     {
       gcc_checking_assert (is_float == other.is_float);
+      gcc_checking_assert (is_vector == other.is_vector);
       if (!is_float)
        cst = wi::mul (cst, other.cst);
       else
@@ -1927,8 +1949,15 @@ struct mult_factor
   void plus (tree other)
     {
       tree other_type = TREE_TYPE (other);
-      gcc_checking_assert ((!is_float && INTEGRAL_TYPE_P (other_type))
-                           || (is_float && SCALAR_FLOAT_TYPE_P (other_type)));
+      gcc_checking_assert ((!is_float
+                           && (INTEGRAL_TYPE_P (other_type)
+                               || VECTOR_INTEGER_TYPE_P (other_type)))
+                           || (is_float && FLOAT_TYPE_P (other_type)));
+
+      gcc_checking_assert (VECTOR_TYPE_P (type) == VECTOR_TYPE_P (other_type));
+      if (VECTOR_TYPE_P (type))
+       other = uniform_vector_p (other);
+
       if (!is_float)
        cst = wi::add (cst, wi::to_wide (other));
       else
@@ -1939,6 +1968,7 @@ struct mult_factor
   void plus (mult_factor &other)
     {
       gcc_checking_assert (is_float == other.is_float);
+      gcc_checking_assert (is_vector == other.is_vector);
       if (!is_float)
        cst = wi::add (cst, other.cst);
       else
@@ -1980,27 +2010,41 @@ struct mult_factor
 
   tree to_tree ()
     {
+      tree scalar_type = is_vector ? TREE_TYPE (type) : type;
+      tree el;
       if (!is_float)
-       return wide_int_to_tree (type, cst);
+       el = wide_int_to_tree (scalar_type, cst);
       else
        {
          REAL_VALUE_TYPE r;
-         real_convert (&r, TYPE_MODE (type), &fcst);
-         return build_real (type, r);
+         real_convert (&r, TYPE_MODE (scalar_type), &fcst);
+         el = build_real (scalar_type, r);
        }
+
+      if (is_vector)
+       return build_vector_from_val (type, el);
+      else
+       return el;
     }
 
   mult_factor (tree t)
     {
       type = TREE_TYPE (t);
-      prec = TYPE_PRECISION (type);
-      if (INTEGRAL_TYPE_P (type))
+      is_vector = false;
+      if (VECTOR_TYPE_P (type))
+       {
+         is_vector = true;
+         t = uniform_vector_p (t);
+       }
+      prec = TYPE_PRECISION (TREE_TYPE (t));
+      if (INTEGRAL_TYPE_P (type)
+         || VECTOR_INTEGER_TYPE_P (type))
        {
          is_float = false;
          cst = wi::to_wide (t);
          fcst = dconst0;
        }
-      else if (SCALAR_FLOAT_TYPE_P (type))
+      else if (FLOAT_TYPE_P (type))
        {
          is_float = true;
          fcst = TREE_REAL_CST (t);
@@ -2010,7 +2054,8 @@ struct mult_factor
     }
 
   mult_factor ()
-    : fcst (dconst0), prec (0), type (NULL_TREE), is_float (false) {}
+    : fcst (dconst0), prec (0), type (NULL_TREE),
+      is_float (false), is_vector (false) {}
 };
 
 struct plus_mult_tree_state
@@ -2063,7 +2108,10 @@ linearize_plus_mult_tree (tree op, mult_factor factor,
                          class loop *loop)
 {
   /* Add constants to the "global" constant.  */
-  if (TREE_CODE (op) == INTEGER_CST || TREE_CODE (op) == REAL_CST)
+  if (TREE_CODE (op) == INTEGER_CST || TREE_CODE (op) == REAL_CST
+      || (TREE_CODE (op) == VECTOR_CST
+         && VECTOR_CST_NELTS (op).is_constant ()
+         && uniform_vector_p (op)))
     {
       if (constant_maybe_expensive (op))
        state->maybe_expensive_constants_before++;
@@ -2078,9 +2126,10 @@ linearize_plus_mult_tree (tree op, mult_factor factor,
   if (TREE_CODE (op) == SSA_NAME
       && can_reassociate_op_p (op)
       && has_single_use (op)
-      && ((INTEGRAL_TYPE_P (TREE_TYPE (op))
+      && (((INTEGRAL_TYPE_P (TREE_TYPE (op))
+           || VECTOR_INTEGER_TYPE_P (TREE_TYPE (op)))
           && TYPE_OVERFLOW_WRAPS (TREE_TYPE (op)))
-         || SCALAR_FLOAT_TYPE_P (TREE_TYPE (op))))
+         || FLOAT_TYPE_P (TREE_TYPE (op))))
     {
       gimple *stmt = SSA_NAME_DEF_STMT (op);
       basic_block bb;
@@ -2098,7 +2147,10 @@ linearize_plus_mult_tree (tree op, mult_factor factor,
            {
              if (opcode == MULT_EXPR
                  && (TREE_CODE (rhs2) == INTEGER_CST
-                     || TREE_CODE (rhs2) == REAL_CST))
+                     || TREE_CODE (rhs2) == REAL_CST
+                     || (TREE_CODE (rhs2) == VECTOR_CST
+                         && VECTOR_CST_NELTS (rhs2).is_constant ()
+                         && uniform_vector_p (rhs2))))
                {
                  state->mults_before++;
                  state->visited.safe_push (stmt);
@@ -2320,15 +2372,15 @@ static bool
 rewrite_plus_mult_tree (gimple *stmt)
 {
   tree lhs = gimple_get_lhs (stmt);
-  gcc_checking_assert ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
-                       || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs))
+  gcc_checking_assert (((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+                        || VECTOR_INTEGER_TYPE_P (TREE_TYPE (lhs)))
+                       || (FLOAT_TYPE_P (TREE_TYPE (lhs))
                            && !HONOR_NANS (TREE_TYPE (lhs))
                            && !HONOR_SIGNED_ZEROS (TREE_TYPE (lhs))))
                       && has_single_use (lhs));
 
   tree type = TREE_TYPE (lhs);
   plus_mult_tree_state state (type);
-
   mult_factor one (build_one_cst (type));
 
   /* Linearize the tree and gather stats about it.  */
@@ -7624,7 +7676,7 @@ reassociate_bb (basic_block bb)
          rhs2 = gimple_assign_rhs2 (stmt);
          tree type = TREE_TYPE (rhs1);
 
-         bool type_can_overflow = INTEGRAL_TYPE_P (type)
+         bool type_can_overflow = ANY_INTEGRAL_TYPE_P (type)
            && TYPE_OVERFLOW_UNDEFINED (type);
 
          bool operation_can_overflow = rhs_code != BIT_IOR_EXPR
@@ -7660,7 +7712,8 @@ reassociate_bb (basic_block bb)
                 do so.  While at it, remove 0-factor elements.  */
              if ((rhs_code == PLUS_EXPR || rhs_code == MULT_EXPR)
                  && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
-                     || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs))
+                     || VECTOR_INTEGER_TYPE_P (TREE_TYPE (lhs))
+                     || (FLOAT_TYPE_P (TREE_TYPE (lhs))
                          && !HONOR_NANS (TREE_TYPE (lhs))
                          && !HONOR_SIGNED_ZEROS (TREE_TYPE (lhs))))
                  && has_single_use (lhs)
-- 
2.54.0

Reply via email to