diff mbox

More forwprop for vectors

Message ID alpine.DEB.2.02.1306122013430.29113@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse June 12, 2013, 8:17 p.m. UTC
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.

Comments

Jeff Law June 12, 2013, 9:06 p.m. UTC | #1
On 06/12/13 14:17, Marc Glisse wrote:
> 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.
This is OK.

Extra credit if you create some testcases.


Thanks,
Jeff
Marc Glisse June 12, 2013, 9:17 p.m. UTC | #2
On Wed, 12 Jun 2013, Jeff Law wrote:

> On 06/12/13 14:17, Marc Glisse wrote:
>> 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.
> This is OK.

Thanks.

> Extra credit if you create some testcases.

I'll try to add one, but the most interesting one would involve a 
BIT_NOT_EXPR of a complex of integers, and I don't have any idea how to 
create that (~ means CONJ_EXPR as a gcc extension), or if it is even 
supposed to be legal.
diff mbox

Patch

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)