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 (¤t, 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 (¤t, 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 (¤t, comb->type); + aff_combination_convert (¤t, 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