[GCC8,30/33] Fold more type conversion into binary arithmetic operations

Submitted by Bin Cheng on April 18, 2017, 10:53 a.m.

Details

Message ID VI1PR0802MB21768EA25D645C5A4F443DD2E7190@VI1PR0802MB2176.eurprd08.prod.outlook.com
State New
Headers show

Commit Message

Bin Cheng April 18, 2017, 10:53 a.m.
Hi,
Simplification of (T1)(X *+- CST) is already implemented in aff_combination_expand,
this patch moves it to tree_to_aff_combination.  It also supports unsigned types
if range information allows the transformation, as well as special case (T1)(X + X).
Is it OK?

Thanks,
bin
2017-04-11  Bin Cheng  <bin.cheng@arm.com>

	* tree-affine.c: Include header file.
	(aff_combination_expand): Move (T1)(X *+- CST) simplification to ...
	(tree_to_aff_combination): ... here.  Support (T1)(X + X) case, and
	unsigned type case if range information allows.
From c3d37447c529793bfdab319574a8a065e7871292 Mon Sep 17 00:00:00 2001
From: Bin Cheng <binche01@e108451-lin.cambridge.arm.com>
Date: Wed, 15 Mar 2017 13:59:09 +0000
Subject: [PATCH 30/33] affine-fold-conversion-to-bin_op-20170224.txt

---
 gcc/tree-affine.c | 82 ++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 60 insertions(+), 22 deletions(-)

Patch hide | download patch | download mbox

diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index 13c477d..6efd1e4 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "rtl.h"
 #include "tree.h"
 #include "gimple.h"
+#include "ssa.h"
 #include "tree-pretty-print.h"
 #include "fold-const.h"
 #include "tree-affine.h"
@@ -363,6 +364,61 @@  tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
       aff_combination_add (comb, &tmp);
       return;
 
+    CASE_CONVERT:
+      {
+	tree otype = TREE_TYPE (expr);
+	tree inner = TREE_OPERAND (expr, 0);
+	tree itype = TREE_TYPE (inner);
+	enum tree_code icode = TREE_CODE (inner);
+
+	/* In principle this is a valid folding, but it isn't necessarily
+	   an optimization, so do it here and not in fold_unary.  */
+	if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR)
+	    && TREE_CODE (itype) == INTEGER_TYPE
+	    && TREE_CODE (otype) == INTEGER_TYPE
+	    && TYPE_PRECISION (otype) > TYPE_PRECISION (itype))
+	  {
+	    tree op0 = TREE_OPERAND (inner, 0), op1 = TREE_OPERAND (inner, 1);
+
+	    /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if X's type has
+	       undefined overflow behavior.  Convert (T1)(X + X) as well.  */
+	    if (TYPE_OVERFLOW_UNDEFINED (itype)
+		&& (TREE_CODE (op1) == INTEGER_CST
+		    || (icode == PLUS_EXPR && operand_equal_p (op0, op1, 0))))
+	      {
+		op0 = fold_convert (otype, op0);
+		op1 = fold_convert (otype, op1);
+		expr = fold_build2 (icode, otype, op0, op1);
+		tree_to_aff_combination (expr, type, comb);
+		return;
+	      }
+	    wide_int minv, maxv;
+	    /* In case X's type has wrapping overflow behavior, we can still
+	       convert (T1)(X - CST) into (T1)X - (T1)CST if X - CST doesn't
+	       overflow by range information.  Also Convert (T1)(X + CST) as
+	       if it's (T1)(X - (-CST)).  */
+	    if (TYPE_UNSIGNED (itype)
+		&& TYPE_OVERFLOW_WRAPS (itype)
+		&& TREE_CODE (op0) == SSA_NAME
+		&& TREE_CODE (op1) == INTEGER_CST
+		&& (icode == PLUS_EXPR || icode == MINUS_EXPR)
+		&& get_range_info (op0, &minv, &maxv) == VR_RANGE)
+	      {
+		if (icode == PLUS_EXPR)
+		  op1 = fold_build1 (NEGATE_EXPR, itype, op1);
+		if (wi::geu_p (minv, op1))
+		  {
+		    op0 = fold_convert (otype, op0);
+		    op1 = fold_convert (otype, op1);
+		    expr = fold_build2 (MINUS_EXPR, otype, op0, op1);
+		    tree_to_aff_combination (expr, type, comb);
+		    return;
+		  }
+	      }
+	  }
+      }
+      break;
+
     default:
       break;
     }
@@ -639,28 +695,10 @@  aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
 	  exp = XNEW (struct name_expansion);
 	  exp->in_progress = 1;
 	  *slot = exp;
-	  /* In principle this is a generally valid folding, but
-	     it is not unconditionally an optimization, so do it
-	     here and not in fold_unary.  */
-	  /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if T1 is wider
-	     than the type of X and overflow for the type of X is
-	     undefined.  */
-	  if (e != name
-	      && INTEGRAL_TYPE_P (type)
-	      && INTEGRAL_TYPE_P (TREE_TYPE (name))
-	      && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (name))
-	      && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (name))
-	      && (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR)
-	      && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
-	    rhs = fold_build2 (code, type,
-			       fold_convert (type, gimple_assign_rhs1 (def)),
-			       fold_convert (type, gimple_assign_rhs2 (def)));
-	  else
-	    {
-	      rhs = gimple_assign_rhs_to_tree (def);
-	      if (e != name)
-		rhs = fold_convert (type, rhs);
-	    }
+	  rhs = gimple_assign_rhs_to_tree (def);
+	  if (e != name)
+	    rhs = fold_convert (type, rhs);
+
 	  tree_to_aff_combination_expand (rhs, comb->type, &current, cache);
 	  exp->expansion = current;
 	  exp->in_progress = 0;