[PATCH 4/5] reassoc: Rewrite vector plus/mult trees.

Robin Dapp <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.