diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-12-20 12:55:45 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-12-20 12:55:45 +0000 |
commit | cc8bea091633989bef6d665c40193a9e255ceb81 (patch) | |
tree | 0198dc636ad0b00daedf03723bb5e7349e3373a3 /gcc/tree-affine.c | |
parent | a90c88042b29b16ecadc2f0560f4d3581bcf9ad6 (diff) | |
download | gcc-cc8bea091633989bef6d665c40193a9e255ceb81.zip gcc-cc8bea091633989bef6d665c40193a9e255ceb81.tar.gz gcc-cc8bea091633989bef6d665c40193a9e255ceb81.tar.bz2 |
poly_int: aff_tree
This patch changes the type of aff_tree::offset from widest_int to
poly_widest_int and adjusts the function interfaces in the same way.
2017-12-20 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* tree-affine.h (aff_tree::offset): Change from widest_int
to poly_widest_int.
(wide_int_ext_for_comb): Delete.
(aff_combination_const, aff_comb_cannot_overlap_p): Take the
constants as poly_widest_int rather than widest_int.
(aff_combination_constant_multiple_p): Return the multiplier
as a poly_widest_int.
(aff_combination_zero_p, aff_combination_singleton_var_p): Handle
polynomial offsets.
* tree-affine.c (wide_int_ext_for_comb): Make original widest_int
version static and add an overload for poly_widest_int.
(aff_combination_const, aff_combination_add_cst)
(wide_int_constant_multiple_p, aff_comb_cannot_overlap_p): Take
the constants as poly_widest_int rather than widest_int.
(tree_to_aff_combination): Generalize INTEGER_CST case to
poly_int_tree_p.
(aff_combination_to_tree): Track offsets as poly_widest_ints.
(aff_combination_add_product, aff_combination_mult): Handle
polynomial offsets.
(aff_combination_constant_multiple_p): Return the multiplier
as a poly_widest_int.
* tree-predcom.c (determine_offset): Return the offset as a
poly_widest_int.
(split_data_refs_to_components, suitable_component_p): Update
accordingly.
(valid_initializer_p): Update call to
aff_combination_constant_multiple_p.
* tree-ssa-address.c (addr_to_parts): Handle polynomial offsets.
* tree-ssa-loop-ivopts.c (get_address_cost_ainc): Take the step
as a poly_int64 rather than a HOST_WIDE_INT.
(get_address_cost): Handle polynomial offsets.
(iv_elimination_compare_lt): Likewise.
(rewrite_use_nonlinear_expr): Likewise.
Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r255888
Diffstat (limited to 'gcc/tree-affine.c')
-rw-r--r-- | gcc/tree-affine.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index 47f56bf..3869b0b 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -34,12 +34,20 @@ along with GCC; see the file COPYING3. If not see /* Extends CST as appropriate for the affine combinations COMB. */ -widest_int +static widest_int wide_int_ext_for_comb (const widest_int &cst, tree type) { return wi::sext (cst, TYPE_PRECISION (type)); } +/* Likewise for polynomial offsets. */ + +static poly_widest_int +wide_int_ext_for_comb (const poly_widest_int &cst, tree type) +{ + return wi::sext (cst, TYPE_PRECISION (type)); +} + /* Initializes affine combination COMB so that its value is zero in TYPE. */ static void @@ -57,7 +65,7 @@ aff_combination_zero (aff_tree *comb, tree type) /* Sets COMB to CST. */ void -aff_combination_const (aff_tree *comb, tree type, const widest_int &cst) +aff_combination_const (aff_tree *comb, tree type, const poly_widest_int &cst) { aff_combination_zero (comb, type); comb->offset = wide_int_ext_for_comb (cst, comb->type);; @@ -190,7 +198,7 @@ aff_combination_add_elt (aff_tree *comb, tree elt, const widest_int &scale_in) /* Adds CST to C. */ static void -aff_combination_add_cst (aff_tree *c, const widest_int &cst) +aff_combination_add_cst (aff_tree *c, const poly_widest_int &cst) { c->offset = wide_int_ext_for_comb (c->offset + cst, c->type); } @@ -268,10 +276,6 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) code = TREE_CODE (expr); switch (code) { - case INTEGER_CST: - aff_combination_const (comb, type, wi::to_widest (expr)); - return; - case POINTER_PLUS_EXPR: tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb); tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp); @@ -423,7 +427,14 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) break; default: - break; + { + if (poly_int_tree_p (expr)) + { + aff_combination_const (comb, type, wi::to_poly_widest (expr)); + return; + } + break; + } } aff_combination_elt (comb, type, expr); @@ -478,7 +489,8 @@ aff_combination_to_tree (aff_tree *comb) { tree type = comb->type, base = NULL_TREE, expr = NULL_TREE; unsigned i; - widest_int off, sgn; + poly_widest_int off; + int sgn; gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE); @@ -502,7 +514,7 @@ aff_combination_to_tree (aff_tree *comb) /* Ensure that we get x - 1, not x + (-1) or x + 0xff..f if x is unsigned. */ - if (wi::neg_p (comb->offset)) + if (known_lt (comb->offset, 0)) { off = -comb->offset; sgn = -1; @@ -588,7 +600,19 @@ aff_combination_add_product (aff_tree *c, const widest_int &coef, tree val, } if (val) - aff_combination_add_elt (r, val, coef * c->offset); + { + if (c->offset.is_constant ()) + /* Access coeffs[0] directly, for efficiency. */ + aff_combination_add_elt (r, val, coef * c->offset.coeffs[0]); + else + { + /* c->offset is polynomial, so multiply VAL rather than COEF + by it. */ + tree offset = wide_int_to_tree (TREE_TYPE (val), c->offset); + val = fold_build2 (MULT_EXPR, TREE_TYPE (val), val, offset); + aff_combination_add_elt (r, val, coef); + } + } else aff_combination_add_cst (r, coef * c->offset); } @@ -607,7 +631,15 @@ aff_combination_mult (aff_tree *c1, aff_tree *c2, aff_tree *r) aff_combination_add_product (c1, c2->elts[i].coef, c2->elts[i].val, r); if (c2->rest) aff_combination_add_product (c1, 1, c2->rest, r); - aff_combination_add_product (c1, c2->offset, NULL, r); + if (c2->offset.is_constant ()) + /* Access coeffs[0] directly, for efficiency. */ + aff_combination_add_product (c1, c2->offset.coeffs[0], NULL, r); + else + { + /* c2->offset is polynomial, so do the multiplication in tree form. */ + tree offset = wide_int_to_tree (c2->type, c2->offset); + aff_combination_add_product (c1, 1, offset, r); + } } /* Returns the element of COMB whose value is VAL, or NULL if no such @@ -776,27 +808,28 @@ free_affine_expand_cache (hash_map<tree, name_expansion *> **cache) is set to true. */ static bool -wide_int_constant_multiple_p (const widest_int &val, const widest_int &div, - bool *mult_set, widest_int *mult) +wide_int_constant_multiple_p (const poly_widest_int &val, + const poly_widest_int &div, + bool *mult_set, poly_widest_int *mult) { - widest_int rem, cst; + poly_widest_int rem, cst; - if (val == 0) + if (known_eq (val, 0)) { - if (*mult_set && *mult != 0) + if (*mult_set && maybe_ne (*mult, 0)) return false; *mult_set = true; *mult = 0; return true; } - if (div == 0) + if (maybe_eq (div, 0)) return false; - if (!wi::multiple_of_p (val, div, SIGNED, &cst)) + if (!multiple_p (val, div, &cst)) return false; - if (*mult_set && *mult != cst) + if (*mult_set && maybe_ne (*mult, cst)) return false; *mult_set = true; @@ -809,12 +842,12 @@ wide_int_constant_multiple_p (const widest_int &val, const widest_int &div, bool aff_combination_constant_multiple_p (aff_tree *val, aff_tree *div, - widest_int *mult) + poly_widest_int *mult) { bool mult_set = false; unsigned i; - if (val->n == 0 && val->offset == 0) + if (val->n == 0 && known_eq (val->offset, 0)) { *mult = 0; return true; @@ -927,23 +960,26 @@ get_inner_reference_aff (tree ref, aff_tree *addr, widest_int *size) size SIZE2 at position DIFF cannot overlap. */ bool -aff_comb_cannot_overlap_p (aff_tree *diff, const widest_int &size1, - const widest_int &size2) +aff_comb_cannot_overlap_p (aff_tree *diff, const poly_widest_int &size1, + const poly_widest_int &size2) { /* Unless the difference is a constant, we fail. */ if (diff->n != 0) return false; - if (wi::neg_p (diff->offset)) + if (!ordered_p (diff->offset, 0)) + return false; + + if (maybe_lt (diff->offset, 0)) { /* The second object is before the first one, we succeed if the last element of the second object is before the start of the first one. */ - return wi::neg_p (diff->offset + size2 - 1); + return known_le (diff->offset + size2, 0); } else { /* We succeed if the second object starts after the first one ends. */ - return size1 <= diff->offset; + return known_le (size1, diff->offset); } } |