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