diff mbox

Small enhancement to associate_plusminus

Message ID 1971449.rxvxeZN2SR@polaris
State New
Headers show

Commit Message

Eric Botcazou May 21, 2014, 7:45 p.m. UTC
Hi,

one of the transformations performed by associate_plusminus is:

  /* Second match patterns that allow contracting a plus-minus pair
     irrespective of overflow issues.

  [...]
	(T)(P + A) - (T)P  -> (T)A

but it is actually applied only to POINTER_PLUS_EXPR and pointer types:

     /* (T)(ptr + adj) - (T)ptr -> (T)adj.  */

It turns out that this pattern arises for size computations of array slices in 
Ada, which are done in integer types; for the attached testcase, extending the 
transformation to integer types makes it possible to eliminate a call to the 
alloca builtin.

Tested on x86_64-suse-linux, OK for the mainline?


2014-05-21  Eric Botcazou  <ebotcazou@adacore.com>

	* tree.h (PLUS_EXPR_CODE_P): New macro.
	(PLUS_EXPR_P): Likewise.
	(CASE_PLUS): Likewise.
	* tree-ssa-forwprop.c (associate_plusminus): Extend (T)(P+A) - (T)P
	-> (T)A transformation to integer types.


2014-05-21  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/opt37.ad[sb]: New test.

Comments

Richard Biener May 22, 2014, 8:07 a.m. UTC | #1
On Wed, May 21, 2014 at 9:45 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> Hi,
>
> one of the transformations performed by associate_plusminus is:
>
>   /* Second match patterns that allow contracting a plus-minus pair
>      irrespective of overflow issues.
>
>   [...]
>         (T)(P + A) - (T)P  -> (T)A
>
> but it is actually applied only to POINTER_PLUS_EXPR and pointer types:
>
>      /* (T)(ptr + adj) - (T)ptr -> (T)adj.  */
>
> It turns out that this pattern arises for size computations of array slices in
> Ada, which are done in integer types; for the attached testcase, extending the
> transformation to integer types makes it possible to eliminate a call to the
> alloca builtin.
>
> Tested on x86_64-suse-linux, OK for the mainline?

I'm a little worried that introducing PLUS_EXPR_CODE_P and friends
invites too easy (not well thought) uses of it - they are distinct enough
that we have very few "common" code-paths given the constraints on
op2 of POINTER_PLUS_EXPR.

Thus I'd say ok without adding those.

Thanks,
Richard.

> 2014-05-21  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * tree.h (PLUS_EXPR_CODE_P): New macro.
>         (PLUS_EXPR_P): Likewise.
>         (CASE_PLUS): Likewise.
>         * tree-ssa-forwprop.c (associate_plusminus): Extend (T)(P+A) - (T)P
>         -> (T)A transformation to integer types.
>
>
> 2014-05-21  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * gnat.dg/opt37.ad[sb]: New test.
>
>
> --
> Eric Botcazou
Eric Botcazou May 22, 2014, 1:39 p.m. UTC | #2
> I'm a little worried that introducing PLUS_EXPR_CODE_P and friends
> invites too easy (not well thought) uses of it - they are distinct enough
> that we have very few "common" code-paths given the constraints on
> op2 of POINTER_PLUS_EXPR.

"grep -A1 -B1 POINTER_PLUS_EXPR *.c" convinced me of the contrary (and I 
planned to post a follow-up patch) but I don't really care in the end.
diff mbox

Patch

Index: tree-ssa-forwprop.c
===================================================================
--- tree-ssa-forwprop.c	(revision 210676)
+++ tree-ssa-forwprop.c	(working copy)
@@ -2642,49 +2642,46 @@  associate_plusminus (gimple_stmt_iterato
 		  gimple_set_modified (stmt, true);
 		}
 	    }
-	  else if (CONVERT_EXPR_CODE_P (def_code) && code == MINUS_EXPR
+	  else if (code == MINUS_EXPR
+		   && CONVERT_EXPR_CODE_P (def_code)
+		   && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
 		   && TREE_CODE (rhs2) == SSA_NAME)
 	    {
-	      /* (T)(ptr + adj) - (T)ptr -> (T)adj.  */
+	      /* (T)(P + A) - (T)P -> (T)A.  */
 	      gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
-	      if (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
-		  && is_gimple_assign (def_stmt2)
+	      if (is_gimple_assign (def_stmt2)
 		  && can_propagate_from (def_stmt2)
 		  && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
 		  && TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
 		{
-		  /* Now we have (T)A - (T)ptr.  */
-		  tree ptr = gimple_assign_rhs1 (def_stmt2);
+		  /* Now we have (T)X - (T)P.  */
+		  tree p = gimple_assign_rhs1 (def_stmt2);
 		  def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
 		  if (is_gimple_assign (def_stmt2)
-		      && gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
-		      && gimple_assign_rhs1 (def_stmt2) == ptr)
+		      && can_propagate_from (def_stmt2)
+		      && PLUS_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
+		      && gimple_assign_rhs1 (def_stmt2) == p)
 		    {
-		      /* And finally (T)(ptr + X) - (T)ptr.  */
-		      tree adj = gimple_assign_rhs2 (def_stmt2);
-		      /* If the conversion of the pointer adjustment to the
-		         final type requires a sign- or zero-extension we
-			 have to punt - it is not defined which one is
-			 correct.  */
-		      if (TYPE_PRECISION (TREE_TYPE (rhs1))
-			  <= TYPE_PRECISION (TREE_TYPE (adj))
-			  || (TREE_CODE (adj) == INTEGER_CST
-			      && tree_int_cst_sign_bit (adj) == 0))
+		      /* And finally (T)(P + A) - (T)P.  */
+		      tree a = gimple_assign_rhs2 (def_stmt2);
+		      /* For pointer types, if the conversion of A to the final
+			 type requires a sign- or zero-extension, then we have
+			 to punt - it is not defined which one is correct.  */
+		      if (!POINTER_TYPE_P (TREE_TYPE (rhs1))
+			  || TYPE_PRECISION (TREE_TYPE (rhs1))
+			     <= TYPE_PRECISION (TREE_TYPE (a))
+			  || (TREE_CODE (a) == INTEGER_CST
+			      && tree_int_cst_sign_bit (a) == 0))
 			{
 			  if (useless_type_conversion_p (TREE_TYPE (rhs1),
-							 TREE_TYPE (adj)))
-			    {
-			      code = TREE_CODE (adj);
-			      rhs1 = adj;
-			    }
+							 TREE_TYPE (a)))
+			    code = TREE_CODE (a);
 			  else
-			    {
-			      code = NOP_EXPR;
-			      rhs1 = adj;
-			    }
+			    code = NOP_EXPR;
+			  rhs1 = a;
 			  rhs2 = NULL_TREE;
 			  gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
-							  NULL_TREE);
+							  rhs2);
 			  gcc_assert (gsi_stmt (*gsi) == stmt);
 			  gimple_set_modified (stmt, true);
 			}
Index: tree.h
===================================================================
--- tree.h	(revision 210676)
+++ tree.h	(working copy)
@@ -439,6 +439,19 @@  extern void omp_clause_range_check_faile
   case NOP_EXPR:						\
   case CONVERT_EXPR
 
+/* Tests if CODE is a plus expr (PLUS_EXPR or POINTER_PLUS_EXPR).  */
+#define PLUS_EXPR_CODE_P(CODE)				\
+  ((CODE) == PLUS_EXPR || (CODE) == POINTER_PLUS_EXPR)
+
+/* Similarly, but accept an expressions instead of a tree code.  */
+#define PLUS_EXPR_P(EXP)	PLUS_EXPR_CODE_P (TREE_CODE (EXP))
+
+/* Generate case for PLUS_EXPR, POINTER_PLUS_EXPR.  */
+
+#define CASE_PLUS						\
+  case PLUS_EXPR:						\
+  case POINTER_PLUS_EXPR
+
 /* Given an expression as a tree, strip any conversion that generates
    no instruction.  Accepts both tree and const_tree arguments since
    we are not modifying the tree itself.  */