Currently, tree-ssa-loop-ivopts assumes that pointers and integers can
be used interchangeably. It prefers to compute everything in unsigned
integer types rather than pointer types.
On a new target that I'm working on, this assumption is problematic;
casting a pointer to an integer and doing arithmetic on the integer
would be much too expensive to be useful. I came up with the patch
below, which makes ivopts try harder to preserve pointer types.
tree-affine is changed to keep track of base pointers, and do arithmetic
(in particular subtraction) properly if base pointers are involved.
Bootstrapped and regression tested with all languages on i686-linux. I
get FAILs in:
* gcc.dg/guality/pr43051-1.c
A somewhat contrived testcase; gdb now produces "optimized out"
messages which I think is acceptable? In any case I remain to be
convinced that this testcase demonstrates any real problem.
* gcc.dg/tree-ssa/reassoc-19.c scan-tree-dump-times reassoc2 " \+ " 0
This seems to fail because we do POINTER_PLUS (ptr, NEG offset))
rather than (char *)((int)ptr - offset). As far as I can tell this
is also not a real problem, but I don't know how to adjust the
testcase.
Comments? Ok?
Bernd
* tree-affine.c (aff_combination_zero): Initialize baseptr.
(aff_combination_add): Handle baseptrs. Abort if both are set.
(aff_combination_diff): New function.
(tree_to_aff_combination_1): Renamed from tree_to_aff_combination.
Remove code to handle pointers; changed to call itself recursively.
(tree_to_aff_combination): New function. Handle the pointer cases
formerly found in the function of the same name, and use
tree_to_aff_combination_1 to compute the offsets.
(aff_combination_to_tree): Build a POINTER_PLUS_EXPR around the
offset if the baseptr is nonnull.
* tree-affine.h (struct affine_tree_combination): New member baseptr.
(aff_combination_diff): Declare.
* tree-predcom.c (determine_offset, valid_initialier_p): Use
aff_combination_diff and return false if it fails.
* tree-ssa-loop-ivopts.c (determine_base_object): If an non-pointer
is cast to a pointer, return the cast.
(add_candidate_1): Use sizetype for steps of a pointer-type iv.
(add_old_iv_candidates): Only add a zero-base pointer candidate if
the precision of pointers and sizetype is equal.
(get_computation_aff): Don't convert steps to pointer types.
Ensure pointers are not scaled. Use aff_combination_diff for
subtraction.
(ptr_difference_cost, difference_cost): Use aff_combination_diff and
return infinite_cost if it fails.
(get_loop_invariant_expr_id): Likewise, returning -1 on failure.
(get_computation_cost_at): Fail if bad pointer expressions would be
generated.
(rewrite_use_nonlinear_expr): Use POINTER_PLUS_EXPR if necessary.
* tree-ssa-address.c (addr_to_parts): Look for a baseptr in the
aff_tree.
* tree-ssa-loop-im.c (mem_refs_may_alias_p): Use aff_combination_diff.
testsuite/
* gcc.dg/tree-ssa/loop-4.c: Scan only for real MEMs, not addresses of
them.
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c (revision 184938)
+++ gcc/tree-ssa-loop-im.c (working copy)
@@ -1772,8 +1772,8 @@ mem_refs_may_alias_p (tree mem1, tree me
get_inner_reference_aff (mem2, &off2, &size2);
aff_combination_expand (&off1, ttae_cache);
aff_combination_expand (&off2, ttae_cache);
- aff_combination_scale (&off1, double_int_minus_one);
- aff_combination_add (&off2, &off1);
+ if (!aff_combination_diff (&off2, &off1))
+ return true;
if (aff_comb_cannot_overlap_p (&off2, size1, size2))
return false;
Index: gcc/testsuite/gcc.dg/tree-ssa/loop-4.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/loop-4.c (revision 184938)
+++ gcc/testsuite/gcc.dg/tree-ssa/loop-4.c (working copy)
@@ -37,7 +37,7 @@ void xxx(void)
/* { dg-final { scan-tree-dump-times " \\* \[^\\n\\r\]*=" 0 "optimized" } } */
/* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\[^&\]MEM" 1 "optimized" } } */
/* And the original induction variable should be eliminated. */
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c (revision 184938)
+++ gcc/tree-ssa-loop-ivopts.c (working copy)
@@ -879,15 +879,21 @@ static tree
determine_base_object (tree expr)
{
enum tree_code code = TREE_CODE (expr);
+ tree type = TREE_TYPE (expr);
tree base, obj;
/* If this is a pointer casted to any type, we need to determine
the base object for the pointer; so handle conversions before
throwing away non-pointer expressions. */
if (CONVERT_EXPR_P (expr))
- return determine_base_object (TREE_OPERAND (expr, 0));
+ {
+ tree op = TREE_OPERAND (expr, 0);
+ if (POINTER_TYPE_P (type) && !POINTER_TYPE_P (TREE_TYPE (op)))
+ return expr;
+ return determine_base_object (op);
+ }
- if (!POINTER_TYPE_P (TREE_TYPE (expr)))
+ if (!POINTER_TYPE_P (type))
return NULL_TREE;
switch (code)
@@ -2225,10 +2231,17 @@ add_candidate_1 (struct ivopts_data *dat
{
orig_type = TREE_TYPE (base);
type = generic_type_for (orig_type);
- if (type != orig_type)
+ if (TREE_CODE (orig_type) == POINTER_TYPE)
{
- base = fold_convert (type, base);
- step = fold_convert (type, step);
+ if (TREE_TYPE (step) != sizetype)
+ step = fold_convert (sizetype, step);
+ }
+ else
+ {
+ if (type != TREE_TYPE (step))
+ step = fold_convert (type, step);
+ if (type != orig_type)
+ base = fold_convert (type, base);
}
}
@@ -2436,16 +2449,20 @@ static void
add_old_iv_candidates (struct ivopts_data *data, struct iv *iv)
{
gimple phi;
- tree def;
+ tree def, basetype;
struct iv_cand *cand;
add_candidate (data, iv->base, iv->step, true, NULL);
/* The same, but with initial value zero. */
- if (POINTER_TYPE_P (TREE_TYPE (iv->base)))
- add_candidate (data, size_int (0), iv->step, true, NULL);
+ basetype = TREE_TYPE (iv->base);
+ if (POINTER_TYPE_P (basetype))
+ {
+ if (TYPE_PRECISION (sizetype) == TYPE_PRECISION (basetype))
+ add_candidate (data, size_int (0), iv->step, true, NULL);
+ }
else
- add_candidate (data, build_int_cst (TREE_TYPE (iv->base), 0),
+ add_candidate (data, build_int_cst (basetype, 0),
iv->step, true, NULL);
phi = SSA_NAME_DEF_STMT (iv->ssa_name);
@@ -2979,10 +2996,12 @@ get_computation_aff (struct loop *loop,
overflows, as all the arithmetics will in the end be performed in UUTYPE
anyway. */
common_type = determine_common_wider_type (&ubase, &cbase);
+ if (!POINTER_TYPE_P (common_type) || POINTER_TYPE_P (ctype))
+ ctype = common_type;
/* use = ubase - ratio * cbase + ratio * var. */
tree_to_aff_combination (ubase, common_type, aff);
- tree_to_aff_combination (cbase, common_type, &cbase_aff);
+ tree_to_aff_combination (cbase, ctype, &cbase_aff);
tree_to_aff_combination (var, uutype, &var_aff);
/* We need to shift the value if we are after the increment. */
@@ -2990,21 +3009,33 @@ get_computation_aff (struct loop *loop,
{
aff_tree cstep_aff;
- if (common_type != uutype)
- cstep_common = fold_convert (common_type, cstep);
- else
- cstep_common = cstep;
+ cstep_common = cstep;
+ if (POINTER_TYPE_P (ctype))
+ {
+ if (TREE_TYPE (cstep) != sizetype)
+ cstep_common = fold_convert (sizetype, cstep);
+ }
+ else if (cbase_aff.type != TREE_TYPE (cstep))
+ cstep_common = fold_convert (ctype, cstep);
- tree_to_aff_combination (cstep_common, common_type, &cstep_aff);
+ tree_to_aff_combination (cstep_common, ctype, &cstep_aff);
aff_combination_add (&cbase_aff, &cstep_aff);
}
- aff_combination_scale (&cbase_aff, double_int_neg (rat));
- aff_combination_add (aff, &cbase_aff);
+ if (!double_int_one_p (rat))
+ {
+ if (cbase_aff.baseptr != NULL_TREE
+ || var_aff.baseptr != NULL_TREE)
+ return false;
+ aff_combination_scale (&cbase_aff, rat);
+ aff_combination_scale (&var_aff, rat);
+ }
+ if (!aff_combination_diff (aff, &cbase_aff))
+ return false;
+
if (common_type != uutype)
aff_combination_convert (aff, uutype);
- aff_combination_scale (&var_aff, rat);
aff_combination_add (aff, &var_aff);
return true;
@@ -3799,8 +3830,8 @@ ptr_difference_cost (struct ivopts_data
type = signed_type_for (TREE_TYPE (e1));
tree_to_aff_combination (e1, type, &aff_e1);
tree_to_aff_combination (e2, type, &aff_e2);
- aff_combination_scale (&aff_e2, double_int_minus_one);
- aff_combination_add (&aff_e1, &aff_e2);
+ if (!aff_combination_diff (&aff_e1, &aff_e2))
+ return infinite_cost;
return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
}
@@ -3854,8 +3885,8 @@ difference_cost (struct ivopts_data *dat
type = signed_type_for (TREE_TYPE (e1));
tree_to_aff_combination (e1, type, &aff_e1);
tree_to_aff_combination (e2, type, &aff_e2);
- aff_combination_scale (&aff_e2, double_int_minus_one);
- aff_combination_add (&aff_e1, &aff_e2);
+ if (!aff_combination_diff (&aff_e1, &aff_e2))
+ return infinite_cost;
return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
}
@@ -3999,8 +4030,9 @@ get_loop_invariant_expr_id (struct ivopt
tree_to_aff_combination (ub, TREE_TYPE (ub), &ubase_aff);
tree_to_aff_combination (cb, TREE_TYPE (cb), &cbase_aff);
- aff_combination_scale (&cbase_aff, shwi_to_double_int (-1 * ratio));
- aff_combination_add (&ubase_aff, &cbase_aff);
+ aff_combination_scale (&cbase_aff, shwi_to_double_int (ratio));
+ if (!aff_combination_diff (&ubase_aff, &cbase_aff))
+ return -1;
expr = aff_combination_to_tree (&ubase_aff);
return get_expr_id (data, expr);
}
@@ -4064,6 +4096,17 @@ get_computation_cost_at (struct ivopts_d
&& !operand_equal_p (use->iv->base_object, cand->iv->base_object, 0))
return infinite_cost;
}
+ /* Eliminate a few other odd cases where we'd end up adding pointers
+ together. Again, this is unlikely to be useful and should only occur
+ in contrived testcases. */
+ if (POINTER_TYPE_P (TREE_TYPE (cand->iv->base))
+ && POINTER_TYPE_P (TREE_TYPE (use->iv->base))
+ && (TREE_CODE (use->iv->base) == INTEGER_CST
+ || TREE_CODE (cand->iv->base) == INTEGER_CST))
+ return infinite_cost;
+ if (POINTER_TYPE_P (TREE_TYPE (cand->iv->base))
+ && !POINTER_TYPE_P (TREE_TYPE (use->iv->base)))
+ return infinite_cost;
if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype))
{
@@ -6179,7 +6222,9 @@ rewrite_use_nonlinear_expr (struct ivopt
step = cand->iv->step;
ctype = TREE_TYPE (step);
utype = TREE_TYPE (cand->var_after);
- if (TREE_CODE (step) == NEGATE_EXPR)
+ if (TREE_CODE (TREE_TYPE (cand->iv->base)) == POINTER_TYPE)
+ incr_code = POINTER_PLUS_EXPR;
+ else if (TREE_CODE (step) == NEGATE_EXPR)
{
incr_code = MINUS_EXPR;
step = TREE_OPERAND (step, 0);
@@ -6213,10 +6258,14 @@ rewrite_use_nonlinear_expr (struct ivopt
/* Otherwise, add the necessary computations to express
the iv. */
- op = fold_convert (ctype, cand->var_before);
- comp = fold_convert (utype,
- build2 (incr_code, ctype, op,
- unshare_expr (step)));
+ op = cand->var_before;
+ if (incr_code == POINTER_PLUS_EXPR)
+ comp = build2 (incr_code, utype, op, unshare_expr (step));
+ else
+ comp = fold_convert (utype,
+ build2 (incr_code, ctype,
+ fold_convert (ctype, op),
+ unshare_expr (step)));
}
else
{
Index: gcc/tree-ssa-address.c
===================================================================
--- gcc/tree-ssa-address.c (revision 184938)
+++ gcc/tree-ssa-address.c (working copy)
@@ -648,7 +648,9 @@ addr_to_parts (tree type, aff_tree *addr
/* Try to find a base of the reference. Since at the moment
there is no reliable way how to distinguish between pointer and its
offset, this is just a guess. */
- if (!parts->symbol && base_hint)
+ if (addr->baseptr != NULL_TREE)
+ parts->base = addr->baseptr;
+ if (!parts->symbol && base_hint && !parts->base)
move_hint_to_base (type, parts, base_hint, addr);
if (!parts->symbol && !parts->base)
move_pointer_to_base (parts, addr);
Index: gcc/tree-data-ref.c
===================================================================
--- gcc/tree-data-ref.c (revision 184938)
+++ gcc/tree-data-ref.c (working copy)
@@ -1362,8 +1362,8 @@ dr_may_alias_p (const struct data_refere
double_int size1, size2;
get_inner_reference_aff (DR_REF (a), &off1, &size1);
get_inner_reference_aff (DR_REF (b), &off2, &size2);
- aff_combination_scale (&off1, double_int_minus_one);
- aff_combination_add (&off2, &off1);
+ if (!aff_combination_diff (&off2, &off1))
+ return true;
if (aff_comb_cannot_overlap_p (&off2, size1, size2))
return false;
}
Index: gcc/tree-affine.c
===================================================================
--- gcc/tree-affine.c (revision 184938)
+++ gcc/tree-affine.c (working copy)
@@ -46,6 +46,7 @@ aff_combination_zero (aff_tree *comb, tr
comb->offset = double_int_zero;
comb->n = 0;
comb->rest = NULL_TREE;
+ comb->baseptr = NULL_TREE;
}
/* Sets COMB to CST. */
@@ -202,6 +203,14 @@ aff_combination_add (aff_tree *comb1, af
{
unsigned i;
+ if (comb2->baseptr != NULL_TREE)
+ {
+ if (comb1->baseptr == NULL_TREE)
+ comb1->baseptr = comb2->baseptr;
+ else
+ gcc_unreachable ();
+ }
+
aff_combination_add_cst (comb1, comb2->offset);
for (i = 0; i < comb2->n; i++)
aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef);
@@ -209,6 +218,44 @@ aff_combination_add (aff_tree *comb1, af
aff_combination_add_elt (comb1, comb2->rest, double_int_one);
}
+/* Subtracts COMB2 from COMB1, storing in COMB1. Returns true on success,
+ false if a failure is encountered (i.e. mismatching base pointers).
+ If FORCE_SIZETYPE is true, we will add the result to a pointer;
+ make sure any base pointers are squashed and the result computed in
+ sizetype. */
+
+bool
+aff_combination_diff (aff_tree *comb1, aff_tree *comb2)
+{
+ tree c1_base = comb1->baseptr;
+ tree c2_base = comb2->baseptr;
+ unsigned i;
+
+ if (c2_base != NULL_TREE)
+ {
+ if (c1_base != NULL_TREE && operand_equal_p (c1_base, c2_base, 0))
+ {
+ comb1->baseptr = NULL_TREE;
+ comb1->type = sizetype;
+ c2_base = c1_base = NULL_TREE;
+ }
+ else
+ {
+ tree val;
+ val = fold_convert (sizetype, c2_base);
+ aff_combination_add_elt (comb1, val, double_int_minus_one);
+ }
+ }
+
+ aff_combination_add_cst (comb1, double_int_neg (comb2->offset));
+ for (i = 0; i < comb2->n; i++)
+ aff_combination_add_elt (comb1, comb2->elts[i].val,
+ double_int_neg (comb2->elts[i].coef));
+ if (comb2->rest)
+ aff_combination_add_elt (comb1, comb2->rest, double_int_minus_one);
+ return true;
+}
+
/* Converts affine combination COMB to TYPE. */
void
@@ -252,17 +299,12 @@ aff_combination_convert (aff_tree *comb,
}
}
-/* Splits EXPR into an affine combination of parts. */
-
-void
-tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
+static void
+tree_to_aff_combination_1 (tree expr, tree type, aff_tree *comb)
{
aff_tree tmp;
enum tree_code code;
- tree cst, core, toffset;
- HOST_WIDE_INT bitpos, bitsize;
- enum machine_mode mode;
- int unsignedp, volatilep;
+ tree cst;
STRIP_NOPS (expr);
@@ -273,16 +315,10 @@ tree_to_aff_combination (tree expr, tree
aff_combination_const (comb, type, tree_to_double_int (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);
- aff_combination_add (comb, &tmp);
- return;
-
case PLUS_EXPR:
case MINUS_EXPR:
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
- tree_to_aff_combination (TREE_OPERAND (expr, 1), type, &tmp);
+ tree_to_aff_combination_1 (TREE_OPERAND (expr, 0), type, comb);
+ tree_to_aff_combination_1 (TREE_OPERAND (expr, 1), type, &tmp);
if (code == MINUS_EXPR)
aff_combination_scale (&tmp, double_int_minus_one);
aff_combination_add (comb, &tmp);
@@ -292,54 +328,22 @@ tree_to_aff_combination (tree expr, tree
cst = TREE_OPERAND (expr, 1);
if (TREE_CODE (cst) != INTEGER_CST)
break;
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+ tree_to_aff_combination_1 (TREE_OPERAND (expr, 0), type, comb);
aff_combination_scale (comb, tree_to_double_int (cst));
return;
case NEGATE_EXPR:
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+ tree_to_aff_combination_1 (TREE_OPERAND (expr, 0), type, comb);
aff_combination_scale (comb, double_int_minus_one);
return;
case BIT_NOT_EXPR:
/* ~x = -x - 1 */
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+ tree_to_aff_combination_1 (TREE_OPERAND (expr, 0), type, comb);
aff_combination_scale (comb, double_int_minus_one);
aff_combination_add_cst (comb, double_int_minus_one);
return;
- case ADDR_EXPR:
- /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
- if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
- {
- expr = TREE_OPERAND (expr, 0);
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
- tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
- aff_combination_add (comb, &tmp);
- return;
- }
- core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
- &toffset, &mode, &unsignedp, &volatilep,
- false);
- if (bitpos % BITS_PER_UNIT != 0)
- break;
- aff_combination_const (comb, type,
- uhwi_to_double_int (bitpos / BITS_PER_UNIT));
- core = build_fold_addr_expr (core);
- if (TREE_CODE (core) == ADDR_EXPR)
- aff_combination_add_elt (comb, core, double_int_one);
- else
- {
- tree_to_aff_combination (core, type, &tmp);
- aff_combination_add (comb, &tmp);
- }
- if (toffset)
- {
- tree_to_aff_combination (toffset, type, &tmp);
- aff_combination_add (comb, &tmp);
- }
- return;
-
case MEM_REF:
if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
tree_to_aff_combination (TREE_OPERAND (TREE_OPERAND (expr, 0), 0),
@@ -366,6 +370,88 @@ tree_to_aff_combination (tree expr, tree
aff_combination_elt (comb, type, expr);
}
+/* Splits EXPR into an affine combination of parts. */
+
+void
+tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
+{
+ aff_tree tmp;
+ enum tree_code code;
+ tree orig_expr = expr;
+ tree expr_type = TREE_TYPE (expr);
+
+ STRIP_NOPS (expr);
+
+ if (!POINTER_TYPE_P (expr_type)
+ || TREE_CODE (expr) == INTEGER_CST)
+ {
+ tree_to_aff_combination_1 (expr, type, comb);
+ return;
+ }
+
+ aff_combination_const (comb, sizetype, double_int_zero);
+ comb->type = expr_type;
+ if (!POINTER_TYPE_P (TREE_TYPE (expr)))
+ {
+ comb->baseptr = orig_expr;
+ return;
+ }
+
+ for (;;)
+ {
+ orig_expr = expr;
+ STRIP_NOPS (expr);
+ code = TREE_CODE (expr);
+ if (code == POINTER_PLUS_EXPR)
+ {
+ tree_to_aff_combination_1 (TREE_OPERAND (expr, 1), sizetype, &tmp);
+ expr = TREE_OPERAND (expr, 0);
+ aff_combination_add (comb, &tmp);
+ }
+ else if (code == ADDR_EXPR)
+ {
+ tree core, toffset;
+ HOST_WIDE_INT bitpos, bitsize;
+ enum machine_mode mode;
+ int unsignedp, volatilep;
+
+ /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.
*/
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
+ {
+ expr = TREE_OPERAND (expr, 0);
+ tree_to_aff_combination_1 (TREE_OPERAND (expr, 1), sizetype,
&tmp);
+ expr = TREE_OPERAND (expr, 0);
+ aff_combination_add (comb, &tmp);
+ continue;
+ }
+ core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
+ &bitpos, &toffset, &mode, &unsignedp,
+ &volatilep, false);
+ if (bitpos % BITS_PER_UNIT != 0)
+ break;
+ aff_combination_const (&tmp, sizetype,
+ uhwi_to_double_int (bitpos / BITS_PER_UNIT));
+ aff_combination_add (comb, &tmp);
+
+ expr = build_fold_addr_expr (core);
+ if (toffset)
+ {
+ tree_to_aff_combination_1 (toffset, sizetype, &tmp);
+ aff_combination_add (comb, &tmp);
+ }
+ if (TREE_CODE (expr) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (expr, 0)) != MEM_REF)
+ {
+ orig_expr = expr;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ comb->baseptr = orig_expr;
+}
+
/* Creates EXPR + ELT * SCALE in TYPE. EXPR is taken from affine
combination COMB. */
@@ -375,6 +461,7 @@ add_elt_to_tree (tree expr, tree type, t
{
enum tree_code code;
tree type1 = type;
+
if (POINTER_TYPE_P (type))
type1 = sizetype;
@@ -435,6 +522,7 @@ aff_combination_to_tree (aff_tree *comb)
{
tree type = comb->type;
tree expr = NULL_TREE;
+ tree baseptr = comb->baseptr;
unsigned i;
double_int off, sgn;
tree type1 = type;
@@ -444,11 +532,11 @@ aff_combination_to_tree (aff_tree *comb)
gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
for (i = 0; i < comb->n; i++)
- expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef,
+ expr = add_elt_to_tree (expr, type1, comb->elts[i].val, comb->elts[i].coef,
comb);
if (comb->rest)
- expr = add_elt_to_tree (expr, type, comb->rest, double_int_one, comb);
+ expr = add_elt_to_tree (expr, type1, comb->rest, double_int_one, comb);
/* Ensure that we get x - 1, not x + (-1) or x + 0xff..f if x is
unsigned. */
@@ -462,8 +550,14 @@ aff_combination_to_tree (aff_tree *comb)
off = comb->offset;
sgn = double_int_one;
}
- return add_elt_to_tree (expr, type, double_int_to_tree (type1, off), sgn,
+ expr = add_elt_to_tree (expr, type1, double_int_to_tree (type1, off), sgn,
comb);
+ if (baseptr != NULL_TREE)
+ expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (baseptr),
+ baseptr, expr);
+ else
+ expr = fold_convert (type, expr);
+ return expr;
}
/* Copies the tree elements of COMB to ensure that they are not shared. */
Index: gcc/tree-affine.h
===================================================================
--- gcc/tree-affine.h (revision 184938)
+++ gcc/tree-affine.h (working copy)
@@ -35,6 +35,9 @@ struct aff_comb_elt
typedef struct affine_tree_combination
{
+ /* A base pointer, added in an outermost POINTER_PLUS_EXPR. */
+ tree baseptr;
+
/* Type of the result of the combination. */
tree type;
@@ -64,6 +67,7 @@ void aff_combination_elt (aff_tree *, tr
void aff_combination_scale (aff_tree *, double_int);
void aff_combination_mult (aff_tree *, aff_tree *, aff_tree *);
void aff_combination_add (aff_tree *, aff_tree *);
+bool aff_combination_diff (aff_tree *, aff_tree *);
void aff_combination_add_elt (aff_tree *, tree, double_int);
void aff_combination_remove_elt (aff_tree *, unsigned);
void aff_combination_convert (aff_tree *, tree);
Index: gcc/tree-predcom.c
===================================================================
--- gcc/tree-predcom.c (revision 184938)
+++ gcc/tree-predcom.c (working copy)
@@ -665,8 +665,8 @@ determine_offset (struct data_reference
is a multiple of step. */
aff_combination_dr_offset (a, &diff);
aff_combination_dr_offset (b, &baseb);
- aff_combination_scale (&baseb, double_int_minus_one);
- aff_combination_add (&diff, &baseb);
+ if (!aff_combination_diff (&diff, &baseb))
+ return false;
tree_to_aff_combination_expand (DR_STEP (a), TREE_TYPE (DR_STEP (a)),
&step, &name_expansions);
@@ -1048,8 +1048,8 @@ valid_initializer_p (struct data_referen
-DISTANCE-th iteration. */
aff_combination_dr_offset (root, &diff);
aff_combination_dr_offset (ref, &base);
- aff_combination_scale (&base, double_int_minus_one);
- aff_combination_add (&diff, &base);
+ if (!aff_combination_diff (&diff, &base))
+ return false;
tree_to_aff_combination_expand (DR_STEP (root), TREE_TYPE (DR_STEP (root)),
&step, &name_expansions);