From: Xionghu Luo <luo...@linux.ibm.com>

Get and propagate value range info to convert expressions with convert
operation on PLUS_EXPR/MINUS_EXPR/MULT_EXPR when not overflow.  i.e.:

(long unsigned int)((unsigned  int)n * 10 + 1)
=>
(long unsigned int)((unsigned  int) n * (long unsigned int)10 + (long unsigned 
int)1)

With this patch for affine combination, load/store motion could detect
more address refs independency and promote some memory expressions to
registers within loop.

PS: Replace the previous "(T1)(X + CST) as (T1)X - (T1)(-CST))"
to "(T1)(X + CST) as (T1)X + (T1)(CST))" for wrapping overflow.

Bootstrap and regression tested pass on Power8-LE.  Any comments?
Thanks.

gcc/ChangeLog

        2020-04-28  Xiong Hu Luo  <luo...@linux.ibm.com>

        PR tree-optimization/83403
        * tree-affine.c (aff_combination_convert): New parameter
        value_range.
        (expr_to_aff_combination): Use range info to check CONVERT
        expr on PLUS_EXPR/MINUS_EXPR/MULT_EXPR.
        (tree_to_aff_combination): Likewise.
        (aff_combination_expand): Get and propagate range info.
        * tree-affine.h: Include value-range.h.
        (aff_combination_convert): New parameter value_range.
        (tree_to_aff_combination): Likewise.
        (aff_combination_expand): Likewise.
---
 gcc/tree-affine.c | 66 +++++++++++++++++++++++++++--------------------
 gcc/tree-affine.h |  8 +++---
 2 files changed, 43 insertions(+), 31 deletions(-)

diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index 0eb8db1b086..63f8acd4c73 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -220,7 +220,7 @@ aff_combination_add (aff_tree *comb1, aff_tree *comb2)
 /* Converts affine combination COMB to TYPE.  */
 
 void
-aff_combination_convert (aff_tree *comb, tree type)
+aff_combination_convert (aff_tree *comb, tree type, value_range *vr)
 {
   unsigned i, j;
   tree comb_type = comb->type;
@@ -228,7 +228,7 @@ aff_combination_convert (aff_tree *comb, tree type)
   if  (TYPE_PRECISION (type) > TYPE_PRECISION (comb_type))
     {
       tree val = fold_convert (type, aff_combination_to_tree (comb));
-      tree_to_aff_combination (val, type, comb);
+      tree_to_aff_combination (val, type, comb, vr);
       return;
     }
 
@@ -263,8 +263,8 @@ aff_combination_convert (aff_tree *comb, tree type)
    true when that was successful and returns the combination in COMB.  */
 
 static bool
-expr_to_aff_combination (aff_tree *comb, tree_code code, tree type,
-                        tree op0, tree op1 = NULL_TREE)
+expr_to_aff_combination (aff_tree *comb, tree_code code, tree type, tree op0,
+                        tree op1 = NULL_TREE, value_range *vr = NULL)
 {
   aff_tree tmp;
   poly_int64 bitpos, bitsize, bytepos;
@@ -279,8 +279,8 @@ expr_to_aff_combination (aff_tree *comb, tree_code code, 
tree type,
 
     case PLUS_EXPR:
     case MINUS_EXPR:
-      tree_to_aff_combination (op0, type, comb);
-      tree_to_aff_combination (op1, type, &tmp);
+      tree_to_aff_combination (op0, type, comb, vr);
+      tree_to_aff_combination (op1, type, &tmp, vr);
       if (code == MINUS_EXPR)
        aff_combination_scale (&tmp, -1);
       aff_combination_add (comb, &tmp);
@@ -289,7 +289,7 @@ expr_to_aff_combination (aff_tree *comb, tree_code code, 
tree type,
     case MULT_EXPR:
       if (TREE_CODE (op1) != INTEGER_CST)
        break;
-      tree_to_aff_combination (op0, type, comb);
+      tree_to_aff_combination (op0, type, comb, vr);
       aff_combination_scale (comb, wi::to_widest (op1));
       return true;
 
@@ -340,27 +340,33 @@ expr_to_aff_combination (aff_tree *comb, tree_code code, 
tree type,
                op1 = fold_convert (otype, op1);
                return expr_to_aff_combination (comb, icode, otype, op0, op1);
              }
-           wide_int minv, maxv;
+
            /* If inner type has wrapping overflow behavior, fold conversion
-              for below case:
-                (T1)(X - CST) -> (T1)X - (T1)CST
-              if X - CST doesn't overflow by range information.  Also handle
-              (T1)(X + CST) as (T1)(X - (-CST)).  */
-           if (TYPE_UNSIGNED (itype)
+              for below cases:
+                (T1)(X *+- CST) -> (T1)X *+- (T1)CST
+              when X *+- CST doesn't overflow by range information.  */
+           if (vr && vr->kind () == VR_RANGE && TYPE_UNSIGNED (itype)
                && TYPE_OVERFLOW_WRAPS (itype)
-               && TREE_CODE (op0) == SSA_NAME
-               && TREE_CODE (op1) == INTEGER_CST
-               && icode != MULT_EXPR
-               && get_range_info (op0, &minv, &maxv) == VR_RANGE)
+               && TREE_CODE (op1) == INTEGER_CST)
              {
-               if (icode == PLUS_EXPR)
-                 op1 = wide_int_to_tree (itype, -wi::to_wide (op1));
-               if (wi::geu_p (minv, wi::to_wide (op1)))
+               wide_int minv, maxv;
+               minv = wi::to_wide (vr->min ());
+               maxv = wi::to_wide (vr->max ());
+               if ((icode == MULT_EXPR || icode == PLUS_EXPR)
+                   && wi::leu_p (maxv, wi::to_wide (TYPE_MAX_VALUE (itype))))
+                 {
+                   op0 = fold_convert (otype, op0);
+                   op1 = fold_convert (otype, op1);
+                   return expr_to_aff_combination (comb, icode, otype, op0,
+                                                   op1, vr);
+                 }
+               else if (icode == MINUS_EXPR
+                        && wi::geu_p (minv, wi::to_wide (op1)))
                  {
                    op0 = fold_convert (otype, op0);
                    op1 = fold_convert (otype, op1);
                    return expr_to_aff_combination (comb, MINUS_EXPR, otype,
-                                                   op0, op1);
+                                                   op0, op1, vr);
                  }
              }
          }
@@ -376,7 +382,7 @@ expr_to_aff_combination (aff_tree *comb, tree_code code, 
tree type,
 /* Splits EXPR into an affine combination of parts.  */
 
 void
-tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
+tree_to_aff_combination (tree expr, tree type, aff_tree *comb, value_range *vr)
 {
   aff_tree tmp;
   enum tree_code code;
@@ -408,10 +414,10 @@ tree_to_aff_combination (tree expr, tree type, aff_tree 
*comb)
     CASE_CONVERT:
       /* ???  TREE_TYPE (expr) should be equal to type here, but IVOPTS
         calls this with not showing an outer widening cast.  */
-      if (expr_to_aff_combination (comb, code,
-                                  TREE_TYPE (expr), TREE_OPERAND (expr, 0)))
+      if (expr_to_aff_combination (comb, code, TREE_TYPE (expr),
+                                  TREE_OPERAND (expr, 0), NULL_TREE, vr))
        {
-         aff_combination_convert (comb, type);
+         aff_combination_convert (comb, type, vr);
          return;
        }
       break;
@@ -709,7 +715,8 @@ public:
 
 void
 aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
-                       hash_map<tree, name_expansion *> **cache)
+                       hash_map<tree, name_expansion *> **cache,
+                       value_range *vr)
 {
   unsigned i;
   aff_tree to_add, current, curre;
@@ -800,7 +807,10 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
          if (!*cache)
            *cache = new hash_map<tree, name_expansion *>;
          (*cache)->put (name, exp);
-         aff_combination_expand (&current, cache);
+         value_range vr = NULL;
+         if (!POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def))))
+           get_range_info (gimple_assign_rhs1 (def), vr);
+         aff_combination_expand (&current, cache, &vr);
          exp->expansion = current;
          exp->in_progress = 0;
        }
@@ -812,7 +822,7 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
          current = exp->expansion;
        }
       if (!useless_type_conversion_p (comb->type, current.type))
-       aff_combination_convert (&current, comb->type);
+       aff_combination_convert (&current, comb->type, vr);
 
       /* Accumulate the new terms to TO_ADD, so that we do not modify
         COMB while traversing it; include the term -coef * E, to remove
diff --git a/gcc/tree-affine.h b/gcc/tree-affine.h
index 4ec4924879d..311e5e7c23a 100644
--- a/gcc/tree-affine.h
+++ b/gcc/tree-affine.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_TREE_AFFINE_H
 #define GCC_TREE_AFFINE_H
 
+#include "value-range.h"
 
 #define MAX_AFF_ELTS 8
 
@@ -73,13 +74,14 @@ void aff_combination_mult (aff_tree *, aff_tree *, aff_tree 
*);
 void aff_combination_add (aff_tree *, aff_tree *);
 void aff_combination_add_elt (aff_tree *, tree, const widest_int &);
 void aff_combination_remove_elt (aff_tree *, unsigned);
-void aff_combination_convert (aff_tree *, tree);
-void tree_to_aff_combination (tree, tree, aff_tree *);
+void aff_combination_convert (aff_tree *, tree, value_range *vr = NULL);
+void tree_to_aff_combination (tree, tree, aff_tree *, value_range *vr = NULL);
 tree aff_combination_to_tree (aff_tree *);
 void unshare_aff_combination (aff_tree *);
 bool aff_combination_constant_multiple_p (aff_tree *, aff_tree *,
                                          poly_widest_int *);
-void aff_combination_expand (aff_tree *, hash_map<tree, name_expansion *> **);
+void aff_combination_expand (aff_tree *, hash_map<tree, name_expansion *> **,
+                            value_range *vr = NULL);
 void tree_to_aff_combination_expand (tree, tree, aff_tree *,
                                     hash_map<tree, name_expansion *> **);
 tree get_inner_reference_aff (tree, aff_tree *, poly_widest_int *);
-- 
2.21.0.777.g83232e3864

Reply via email to