This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: More forwprop for vectors


On Wed, 12 Jun 2013, Marc Glisse wrote:

I suppose it's explicitely not allowing complex integer constants?

Hmm... Thanks, I keep forgetting complex :-(

And complex is even more of a pain than vector to handle.

Testing for CONSTANT_CLASS_P seems sufficient here. Some transformations also seem valid for complex, and the others are already restricted by the fact that they involve operators like AND or XOR, or because we exit early for FLOAT_TYPE_P and FIXED_POINT_TYPE_P. I'll test that (no new macro for now then).

Here is a new version. I added a build_all_ones_cst helper which currently only handles integer-like (complex, vector) types.

Bootstrap+testsuite on x86_64-unknown-linux-gnu as usual.

2013-06-13  Marc Glisse  <marc.glisse@inria.fr>

	* tree-ssa-forwprop.c (simplify_bitwise_binary, associate_plusminus):
	Generalize to complex and vector.
	* tree.c (build_all_ones_cst): New function.
	* tree.h (build_all_ones_cst): Declare it.

--
Marc Glisse
Index: tree-ssa-forwprop.c
===================================================================
--- tree-ssa-forwprop.c	(revision 200005)
+++ tree-ssa-forwprop.c	(working copy)
@@ -1971,22 +1971,22 @@ simplify_bitwise_binary (gimple_stmt_ite
 	  gimple_assign_set_rhs2 (stmt, b);
 	  gimple_assign_set_rhs_code (stmt, def1_code);
 	  update_stmt (stmt);
 	  return true;
 	}
     }
 
   /* (a | CST1) & CST2  ->  (a & CST2) | (CST1 & CST2).  */
   if (code == BIT_AND_EXPR
       && def1_code == BIT_IOR_EXPR
-      && TREE_CODE (arg2) == INTEGER_CST
-      && TREE_CODE (def1_arg2) == INTEGER_CST)
+      && CONSTANT_CLASS_P (arg2)
+      && CONSTANT_CLASS_P (def1_arg2))
     {
       tree cst = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg2),
 			      arg2, def1_arg2);
       tree tem;
       gimple newop;
       if (integer_zerop (cst))
 	{
 	  gimple_assign_set_rhs1 (stmt, def1_arg1);
 	  update_stmt (stmt);
 	  return true;
@@ -2002,34 +2002,33 @@ simplify_bitwise_binary (gimple_stmt_ite
       gimple_assign_set_rhs_code (stmt, BIT_IOR_EXPR);
       update_stmt (stmt);
       return true;
     }
 
   /* Combine successive equal operations with constants.  */
   if ((code == BIT_AND_EXPR
        || code == BIT_IOR_EXPR
        || code == BIT_XOR_EXPR)
       && def1_code == code 
-      && TREE_CODE (arg2) == INTEGER_CST
-      && TREE_CODE (def1_arg2) == INTEGER_CST)
+      && CONSTANT_CLASS_P (arg2)
+      && CONSTANT_CLASS_P (def1_arg2))
     {
       tree cst = fold_build2 (code, TREE_TYPE (arg2),
 			      arg2, def1_arg2);
       gimple_assign_set_rhs1 (stmt, def1_arg1);
       gimple_assign_set_rhs2 (stmt, cst);
       update_stmt (stmt);
       return true;
     }
 
   /* Canonicalize X ^ ~0 to ~X.  */
   if (code == BIT_XOR_EXPR
-      && TREE_CODE (arg2) == INTEGER_CST
       && integer_all_onesp (arg2))
     {
       gimple_assign_set_rhs_with_ops (gsi, BIT_NOT_EXPR, arg1, NULL_TREE);
       gcc_assert (gsi_stmt (*gsi) == stmt);
       update_stmt (stmt);
       return true;
     }
 
   /* Try simple folding for X op !X, and X op X.  */
   res = simplify_bitwise_binary_1 (code, TREE_TYPE (arg1), arg1, arg2);
@@ -2472,73 +2471,74 @@ associate_plusminus (gimple_stmt_iterato
 		       && code != def_code)
 		{
 		  /* (A +- B) -+ B -> A.  */
 		  code = TREE_CODE (def_rhs1);
 		  rhs1 = def_rhs1;
 		  rhs2 = NULL_TREE;
 		  gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
 		  gcc_assert (gsi_stmt (*gsi) == stmt);
 		  gimple_set_modified (stmt, true);
 		}
-	      else if (TREE_CODE (rhs2) == INTEGER_CST
-		       && TREE_CODE (def_rhs1) == INTEGER_CST)
+	      else if (CONSTANT_CLASS_P (rhs2)
+		       && CONSTANT_CLASS_P (def_rhs1))
 		{
 		  /* (CST +- A) +- CST -> CST +- A.  */
 		  tree cst = fold_binary (code, TREE_TYPE (rhs1),
 					  def_rhs1, rhs2);
 		  if (cst && !TREE_OVERFLOW (cst))
 		    {
 		      code = def_code;
 		      gimple_assign_set_rhs_code (stmt, code);
 		      rhs1 = cst;
 		      gimple_assign_set_rhs1 (stmt, rhs1);
 		      rhs2 = def_rhs2;
 		      gimple_assign_set_rhs2 (stmt, rhs2);
 		      gimple_set_modified (stmt, true);
 		    }
 		}
-	      else if (TREE_CODE (rhs2) == INTEGER_CST
-		       && TREE_CODE (def_rhs2) == INTEGER_CST
+	      else if (CONSTANT_CLASS_P (rhs2)
+		       && CONSTANT_CLASS_P (def_rhs2)
 		       && def_code == PLUS_EXPR)
 		{
 		  /* (A + CST) +- CST -> A + CST.  */
 		  tree cst = fold_binary (code, TREE_TYPE (rhs1),
 					  def_rhs2, rhs2);
 		  if (cst && !TREE_OVERFLOW (cst))
 		    {
 		      code = PLUS_EXPR;
 		      gimple_assign_set_rhs_code (stmt, code);
 		      rhs1 = def_rhs1;
 		      gimple_assign_set_rhs1 (stmt, rhs1);
 		      rhs2 = cst;
 		      gimple_assign_set_rhs2 (stmt, rhs2);
 		      gimple_set_modified (stmt, true);
 		    }
 		}
 	    }
-	  else if (def_code == BIT_NOT_EXPR
-		   && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
+	  else if (def_code == BIT_NOT_EXPR && code == PLUS_EXPR)
 	    {
 	      tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
-	      if (code == PLUS_EXPR
-		  && operand_equal_p (def_rhs1, rhs2, 0))
+	      if (operand_equal_p (def_rhs1, rhs2, 0))
 		{
 		  /* ~A + A -> -1.  */
-		  code = INTEGER_CST;
-		  rhs1 = build_int_cst_type (TREE_TYPE (rhs2), -1);
+		  rhs1 = build_all_ones_cst (TREE_TYPE (rhs2));
 		  rhs2 = NULL_TREE;
+		  code = TREE_CODE (rhs1);
 		  gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
 		  gcc_assert (gsi_stmt (*gsi) == stmt);
 		  gimple_set_modified (stmt, true);
 		}
-	      else if (code == PLUS_EXPR
-		       && integer_onep (rhs1))
+	      else if ((TREE_CODE (TREE_TYPE (rhs1)) != COMPLEX_TYPE
+			&& integer_onep (rhs1))
+		       || (TREE_CODE (rhs1) == COMPLEX_CST
+			   && integer_onep (TREE_REALPART (rhs1))
+			   && integer_onep (TREE_IMAGPART (rhs1))))
 		{
 		  /* ~A + 1 -> -A.  */
 		  code = NEGATE_EXPR;
 		  rhs1 = def_rhs1;
 		  rhs2 = NULL_TREE;
 		  gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
 		  gcc_assert (gsi_stmt (*gsi) == stmt);
 		  gimple_set_modified (stmt, true);
 		}
 	    }
@@ -2573,66 +2573,65 @@ associate_plusminus (gimple_stmt_iterato
 		{
 		  /* A +- (B +- A) -> +- B.  */
 		  code = ((code == PLUS_EXPR)
 			  ? TREE_CODE (def_rhs1) : NEGATE_EXPR);
 		  rhs1 = def_rhs1;
 		  rhs2 = NULL_TREE;
 		  gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
 		  gcc_assert (gsi_stmt (*gsi) == stmt);
 		  gimple_set_modified (stmt, true);
 		}
-	      else if (TREE_CODE (rhs1) == INTEGER_CST
-		       && TREE_CODE (def_rhs1) == INTEGER_CST)
+	      else if (CONSTANT_CLASS_P (rhs1)
+		       && CONSTANT_CLASS_P (def_rhs1))
 		{
 		  /* CST +- (CST +- A) -> CST +- A.  */
 		  tree cst = fold_binary (code, TREE_TYPE (rhs2),
 					  rhs1, def_rhs1);
 		  if (cst && !TREE_OVERFLOW (cst))
 		    {
 		      code = (code == def_code ? PLUS_EXPR : MINUS_EXPR);
 		      gimple_assign_set_rhs_code (stmt, code);
 		      rhs1 = cst;
 		      gimple_assign_set_rhs1 (stmt, rhs1);
 		      rhs2 = def_rhs2;
 		      gimple_assign_set_rhs2 (stmt, rhs2);
 		      gimple_set_modified (stmt, true);
 		    }
 		}
-	      else if (TREE_CODE (rhs1) == INTEGER_CST
-		       && TREE_CODE (def_rhs2) == INTEGER_CST)
+	      else if (CONSTANT_CLASS_P (rhs1)
+		       && CONSTANT_CLASS_P (def_rhs2))
 		{
 		  /* CST +- (A +- CST) -> CST +- A.  */
 		  tree cst = fold_binary (def_code == code
 					  ? PLUS_EXPR : MINUS_EXPR,
 					  TREE_TYPE (rhs2),
 					  rhs1, def_rhs2);
 		  if (cst && !TREE_OVERFLOW (cst))
 		    {
 		      rhs1 = cst;
 		      gimple_assign_set_rhs1 (stmt, rhs1);
 		      rhs2 = def_rhs1;
 		      gimple_assign_set_rhs2 (stmt, rhs2);
 		      gimple_set_modified (stmt, true);
 		    }
 		}
 	    }
-	  else if (def_code == BIT_NOT_EXPR
-		   && INTEGRAL_TYPE_P (TREE_TYPE (rhs2)))
+	  else if (def_code == BIT_NOT_EXPR)
 	    {
 	      tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
 	      if (code == PLUS_EXPR
 		  && operand_equal_p (def_rhs1, rhs1, 0))
 		{
 		  /* A + ~A -> -1.  */
-		  code = INTEGER_CST;
-		  rhs1 = build_int_cst_type (TREE_TYPE (rhs1), -1);
+		  rhs1 = build_all_ones_cst (TREE_TYPE (rhs1));
 		  rhs2 = NULL_TREE;
+		  code = TREE_CODE (rhs1);
 		  gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
 		  gcc_assert (gsi_stmt (*gsi) == stmt);
 		  gimple_set_modified (stmt, true);
 		}
 	    }
 	}
     }
 
 out:
   if (gimple_modified_p (stmt))
Index: tree.c
===================================================================
--- tree.c	(revision 200005)
+++ tree.c	(working copy)
@@ -1636,20 +1636,35 @@ build_one_cst (tree type)
     case COMPLEX_TYPE:
       return build_complex (type,
 			    build_one_cst (TREE_TYPE (type)),
 			    build_zero_cst (TREE_TYPE (type)));
 
     default:
       gcc_unreachable ();
     }
 }
 
+/* Return an integer of type TYPE containing all 1's in as much precision as
+   it contains, or a complex or vector whose subparts are such integers.  */
+
+tree
+build_all_ones_cst (tree type)
+{
+  if (TREE_CODE (type) == COMPLEX_TYPE)
+    {
+      tree scalar = build_all_ones_cst (TREE_TYPE (type));
+      return build_complex (type, scalar, scalar);
+    }
+  else
+    return build_minus_one_cst (type);
+}
+
 /* Return a constant of arithmetic type TYPE which is the
    opposite of the multiplicative identity of the set TYPE.  */
 
 tree
 build_minus_one_cst (tree type)
 {
   switch (TREE_CODE (type))
     {
     case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
     case POINTER_TYPE: case REFERENCE_TYPE:
Index: tree.h
===================================================================
--- tree.h	(revision 200005)
+++ tree.h	(working copy)
@@ -4761,20 +4761,21 @@ extern tree build_vector_stat (tree, tre
 extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *);
 extern tree build_vector_from_val (tree, tree);
 extern tree build_constructor (tree, vec<constructor_elt, va_gc> *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
 extern tree build_constructor_va (tree, int, ...);
 extern tree build_real_from_int_cst (tree, const_tree);
 extern tree build_complex (tree, tree, tree);
 extern tree build_one_cst (tree);
 extern tree build_minus_one_cst (tree);
+extern tree build_all_ones_cst (tree);
 extern tree build_zero_cst (tree);
 extern tree build_string (int, const char *);
 extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
 #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
 extern tree build_tree_list_vec_stat (const vec<tree, va_gc> *MEM_STAT_DECL);
 #define build_tree_list_vec(v) build_tree_list_vec_stat (v MEM_STAT_INFO)
 extern tree build_decl_stat (location_t, enum tree_code,
 			     tree, tree MEM_STAT_DECL);
 extern tree build_fn_decl (const char *, tree);
 #define build_decl(l,c,t,q) build_decl_stat (l,c,t,q MEM_STAT_INFO)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]