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.ch...@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 <binch...@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(-)

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;
-- 
1.9.1

Reply via email to