On Mon, Sep 7, 2026 at 1:41 AM Hongtao Liu <[email protected]> wrote: > > On Mon, Sep 7, 2026 at 3:08 PM Andrea Pinski > <[email protected]> wrote: > > > > On Sun, Sep 6, 2026 at 11:44 PM liuhongt <[email protected]> wrote: > > > > > > r15-6657 canonicalized signed arithmetic to unsigned, exposing a 17.5% > > > code-size regression in SPEC CPU2017 507.cactuBSSN_r at -O2. The > > > resulting > > > nested sign-changing conversions and unsigned additions hide the common > > > induction variable from affine decomposition, causing IVOPTS to create an > > > extra outer-loop invariant. > > > > > > The fix also slightly improves 507.cactuBSSN_r performance and improves > > > 548.exchange2_r by about 6% on Intel GNR, AMD Zen 5, and Arm Graviton 5. > > > Since r15-6657 primarily regressed outer-loop IV computations, this is a > > > general improvement for workloads sensitive to outer-loop performance. > > > > > > tree-affine normally uses the global range query, which ignores statement > > > context for SSA names. It therefore cannot prove that the conversions > > > preserve values or that modular additions do not wrap, even when both are > > > known at the IV use. Create a local ranger in IVOPTS and pass the use > > > statement to affine decomposition, making these contextual facts available > > > and allowing the common induction variable to cancel. Keep candidate > > > elimination bounds on context-free ranges because those bounds may be > > > materialized in the loop preheader. > > > > I am not sure why not create a global one? > Do you mean using enable_ranger (cfun)/disable_ranger(cfun) instead of > creating a local ranger? > Yes that should be simpler, though we still need to pass contextual stmt down. > > > > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. > > > Ok for trunk? > > > > > > gcc/ChangeLog: > > > > > > PR tree-optimization/126486 > > > * tree-affine.cc (expr_to_aff_combination): Accept statement and > > > range-query context. Handle range-preserving sign changes and > > > unsigned modular additions. > > > (tree_to_aff_combination): Accept and propagate statement and > > > range > > > query context. > > > * tree-affine.h (tree_to_aff_combination): Update declaration. > > > * tree-ssa-loop-ivopts.cc: Include gimple-range.h. > > > (ivopts_data::ranger): New member. > > > (tree_ssa_iv_optimize_init): Initialize it. > > > (get_computation_aff_1): Pass statement-local range context. > > > (cand_value_at): Explain why statement-local ranges are not used. > > > (tree_ssa_iv_optimize): Create a ranger for affine computations. > > > > > > gcc/testsuite/ChangeLog: > > > > > > PR tree-optimization/126486 > > > * gcc.dg/tree-ssa/pr126486.c: New test. > > > > > > Assisted-by: openai.gpt-5.6-sol xhigh <[email protected]> > > > > Can you describe which part was assisted here? > Explained below. > > > > > > --- > > > gcc/testsuite/gcc.dg/tree-ssa/pr126486.c | 29 ++++ > > > gcc/tree-affine.cc | 160 ++++++++++++++++++++--- > > > gcc/tree-affine.h | 4 +- > > > gcc/tree-ssa-loop-ivopts.cc | 20 ++- > > > 4 files changed, 188 insertions(+), 25 deletions(-) > > > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126486.c > > > > > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126486.c > > > b/gcc/testsuite/gcc.dg/tree-ssa/pr126486.c > > > new file mode 100644 > > > index 00000000000..7ec81e2ecdd > > > --- /dev/null > > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126486.c > > > @@ -0,0 +1,29 @@ > > > +/* PR tree-optimization/126486 */ > > > +/* { dg-do compile { target lp64 } } */ > > > +/* { dg-options "-O2 -fdump-tree-ivopts-details" } */ > > > + > > > +int > > > +foo (int n_dims, int *actual_indices, const long *input_array_dims, > > > + int max_iter) > > > +{ > > > + int sum = 0; > > > + int iter = 0; > > > + > > > + while (iter < max_iter) > > > + { > > > + sum = actual_indices[0]; > > > + for (int k = n_dims - 1; k > 0; k--) > > > + { > > > + int product = 1; > > > + for (int j = k - 1; j >= 0; j--) > > > + product *= input_array_dims[j]; > > > + sum += actual_indices[k] * product; > > > + } > > > + iter++; > > > + } > > > + return sum; > > > +} > > > + > > > +/* The only invariant expression containing both K and INPUT_ARRAY_DIMS > > > + should be the base of the address candidate. */ > > > +/* { dg-final { scan-tree-dump-times "inv_expr \[0-9\]+:.*\\(unsigned > > > long\\) k_\[0-9\]+ \\* 8 \\+ \\(unsigned long\\) input_array_dims" 1 > > > "ivopts" } } */ > > > diff --git a/gcc/tree-affine.cc b/gcc/tree-affine.cc > > > index 181fd6fb33c..89e3cf207fc 100644 > > > --- a/gcc/tree-affine.cc > > > +++ b/gcc/tree-affine.cc > > > @@ -265,22 +265,23 @@ aff_combination_convert (aff_tree *comb, tree type) > > > > > > static bool > > > expr_to_aff_combination (aff_tree *comb, tree_code code, tree type, > > > - tree op0, tree op1 = NULL_TREE) > > > + tree op0, tree op1 = NULL_TREE, gimple *at = > > > NULL, > > > + range_query *query = NULL) > > > { > > > aff_tree tmp; > > > > > > switch (code) > > > { > > > case POINTER_PLUS_EXPR: > > > - tree_to_aff_combination (op0, type, comb); > > > - tree_to_aff_combination (op1, sizetype, &tmp); > > > + tree_to_aff_combination (op0, type, comb, at, query); > > > + tree_to_aff_combination (op1, sizetype, &tmp, at, query); > > > aff_combination_add (comb, &tmp); > > > return true; > > > > > > 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, at, query); > > > + tree_to_aff_combination (op1, type, &tmp, at, query); > > > if (code == MINUS_EXPR) > > > aff_combination_scale (&tmp, -1); > > > aff_combination_add (comb, &tmp); > > > @@ -289,18 +290,18 @@ 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, at, query); > > > aff_combination_scale (comb, wi::to_widest (op1)); > > > return true; > > > > > > case NEGATE_EXPR: > > > - tree_to_aff_combination (op0, type, comb); > > > + tree_to_aff_combination (op0, type, comb, at, query); > > > aff_combination_scale (comb, -1); > > > return true; > > > > > > case BIT_NOT_EXPR: > > > /* ~x = -x - 1 */ > > > - tree_to_aff_combination (op0, type, comb); > > > + tree_to_aff_combination (op0, type, comb, at, query); > > > aff_combination_scale (comb, -1); > > > aff_combination_add_cst (comb, -1); > > > return true; > > > @@ -311,14 +312,108 @@ expr_to_aff_combination (aff_tree *comb, tree_code > > > code, tree type, > > > tree inner = op0; > > > tree itype = TREE_TYPE (inner); > > > enum tree_code icode = TREE_CODE (inner); > > > + range_query *rquery = query; > > > > > > /* STRIP_NOPS */ > > > if (tree_nop_conversion_p (otype, itype)) > > > { > > > - tree_to_aff_combination (op0, type, comb); > > > + tree_to_aff_combination (op0, type, comb, at, query); > > > return true; > > > } > > > > > > + /* Remove a same-precision sign-changing intermediate conversion > > > when > > > + range information proves that it preserves the value. */ > > > + if (CONVERT_EXPR_P (inner) > > > + && TREE_CODE (otype) == INTEGER_TYPE > > > + && TREE_CODE (itype) == INTEGER_TYPE > > > > These all should be using INTEGRAL_NB_TYPE_P rather than a direct > > comparison against INTEGER_TYPE. I fixed a bunch of cases where there > > was a comparison against INTEGER_TYPE in r17-89-g78280307c78ead. The > > direct comparison against INTEGER_TYPE makes me worried this part was > > created by a LLM. > > Most of the simplified code is written by myself and polished by AI, > i'm following the existing simplification in expr_to_aff_combination > which uses TREE_CODE (itype) == INTEGER_TYPE.(didn't notice > r17-89-g78280307c78ead) > > /* In principle this is a valid folding, but it isn't necessarily > an optimization, so do it here and not in fold_unary. */ > if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR) > && TREE_CODE (itype) == INTEGER_TYPE > && TREE_CODE (otype) == INTEGER_TYPE > && TYPE_PRECISION (otype) > TYPE_PRECISION (itype)) > { > tree op0 = TREE_OPERAND (inner, 0), op1 = TREE_OPERAND (inner, 1); > > /* If inner type has undefined overflow behavior, fold conversion > for below two cases: > (T1)(X *+- CST) -> (T1)X *+- (T1)CST > (T1)(X + X) -> (T1)X + (T1)X. */ > if (TYPE_OVERFLOW_UNDEFINED (itype) > && (TREE_CODE (op1) == INTEGER_CST > || (icode == PLUS_EXPR && operand_equal_p (op0, op1, 0)))) > > I'm also using AI to root cause the issue in the PR, do many > investigation with different approach(.i.e optimize off the redundancy > of the invariant created by inner loop in the find_interesting_uses > when outer loops is processed .etc), drafted the code which passed > down the new parameter of local ranger and contextual stmt(there's > many different places, I think AI can handle better than me for that > part) > > Agree that INTEGRAL_NB_TYPE_P is better. > > > > > > + && TYPE_PRECISION (otype) > TYPE_PRECISION (itype)) > > > + { > > > + tree inner_op = TREE_OPERAND (inner, 0); > > > + tree inner_type = TREE_TYPE (inner_op); > > > + > > > + if (TREE_CODE (inner_type) == INTEGER_TYPE > > > + && TYPE_PRECISION (inner_type) == TYPE_PRECISION (itype) > > > + && TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (itype)) > > > > Why not just use tree_nop_conversion_p here? > > Yes, should be better with tree_nop_conversion_p. > > > > > + { > > > + int_range_max vr; > > > + > > > + if (!rquery) > > > + rquery = get_range_query (cfun); > > > + if (rquery->range_of_expr (vr, inner_op, at) > > > + && !vr.varying_p () > > > + && !vr.undefined_p () > > > + && (TYPE_UNSIGNED (inner_type) > > > + ? !wi::neg_p (vr.upper_bound (), SIGNED) > > > + : !wi::neg_p (vr.lower_bound (), SIGNED))) > > > > I am trying to understand what values here are being compared. Are > > you just asking if the bounds has the upper bit not set? Maybe use > > nonzero bits would be easier to deal with that instead of comparing > > the lower/upper bounds of the range. > Yes, wi::neg_p (vr.get_nonzero_bits (), SIGNED) should be more clear. > > > > > > + { > > > + inner_op = fold_convert (otype, inner_op); > > > + tree_to_aff_combination (inner_op, type, comb, at, > > > query); > > > + return true; > > > + } > > > + } > > > + } > > > > I wonder if this could not be done in match in general too. > The redundant expression is intermediate expr generated in ivopts, and > it impacts ivopt decision for the outer loop, it's not final stmt > generated by ivopt, so a general match may be not suitable. > > > > > > + > > > + /* Handle a sign-changing conversion between an unsigned operation > > > + and a wider conversion: > > > + > > > + (T1) (T2) ((U) X + CST) > > > + > > > + where T2 and U have the same precision and T2 is signed. If > > > the > > > + operation interpreted in T2 does not overflow, distribute the > > > + conversion through the operation. */ > > > + if (CONVERT_EXPR_P (inner) > > > + && TREE_CODE (otype) == INTEGER_TYPE > > > + && TREE_CODE (itype) == INTEGER_TYPE > > > > Again with the direct comparison to INTEGER_TYPE. > Will change. > > > > > + && !TYPE_UNSIGNED (itype) > > > + && TYPE_PRECISION (otype) > TYPE_PRECISION (itype)) > > > + { > > > + tree wrapped = TREE_OPERAND (inner, 0); > > > + tree wtype = TREE_TYPE (wrapped); > > > + tree_code wcode = TREE_CODE (wrapped); > > > + > > > + if ((wcode == PLUS_EXPR || wcode == MINUS_EXPR) > > > + && TREE_CODE (wtype) == INTEGER_TYPE > > > + && TYPE_UNSIGNED (wtype) > > > + && TYPE_PRECISION (wtype) == TYPE_PRECISION (itype) > > > + && TREE_CODE (TREE_OPERAND (wrapped, 1)) == INTEGER_CST) > > > + { > > > + tree wop0 = fold_convert (itype, TREE_OPERAND (wrapped, > > > 0)); > > > + tree wop1 = fold_convert (itype, TREE_OPERAND (wrapped, > > > 1)); > > > + int_range_max vr; > > > + > > > + if (!rquery) > > > + rquery = get_range_query (cfun); > > > + if (rquery->range_of_expr (vr, wop0, at) > > > + && !vr.varying_p () > > > + && !vr.undefined_p ()) > > > + { > > > + wi::overflow_type ovf1 = wi::OVF_NONE; > > > + wi::overflow_type ovf2 = wi::OVF_NONE; > > > + wide_int cst = wi::to_wide (wop1); > > > + > > > + if (wcode == PLUS_EXPR) > > > + { > > > + wi::add (vr.lower_bound (), cst, SIGNED, &ovf1); > > > + wi::add (vr.upper_bound (), cst, SIGNED, &ovf2); > > > + } > > > + else > > > + { > > > + wi::sub (vr.lower_bound (), cst, SIGNED, &ovf1); > > > + wi::sub (vr.upper_bound (), cst, SIGNED, &ovf2); > > > + } > > > > You should just use `range_op_handler (wcode).overflow_free_p (vr0, > > vr1)` here. Should simplify this. > If the operation is performed with an actual wrapped type, yes. > But here the stmt sequence is (T1) (T2) ((U) X + CST), T2 is > signed(not the actual final operation type) and will always return > true since signed overflow is UD, but it's not correct > > cut from operator_plus::overflow_free_p: > tree type = lh.type (); > if (TYPE_OVERFLOW_UNDEFINED (type)) > return true; > > .i.e > We're trying to prove (long) (int) ((unsigned) X + 1) is not > overflow, it return true since T2(int) is signed, but when X is > INT_MAX, simplify it to INT_MAX + 1L is not correct > A extend to a wider type and check that fits to T2 is needed.
Note I filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127356 for new version of overflow_free_p because I need a similar thing for something which I am working on; for now I just punted on non unsigned types too. I might add a version next week as I think I need it for another case I am going to be working on too. Thanks, Andrea > > > > > + > > > + if (ovf1 == wi::OVF_NONE && ovf2 == wi::OVF_NONE) > > > + { > > > + wop0 = fold_convert (otype, wop0); > > > + wop1 = fold_convert (otype, wop1); > > > + return expr_to_aff_combination (comb, wcode, > > > otype, > > > + wop0, wop1, at, > > > + query); > > > + } > > > + } > > > + } > > > + } > > > + > > > /* In principle this is a valid folding, but it isn't necessarily > > > an optimization, so do it here and not in fold_unary. */ > > > if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == > > > MULT_EXPR) > > > @@ -338,7 +433,8 @@ expr_to_aff_combination (aff_tree *comb, tree_code > > > code, tree type, > > > { > > > op0 = fold_convert (otype, op0); > > > op1 = fold_convert (otype, op1); > > > - return expr_to_aff_combination (comb, icode, otype, op0, > > > op1); > > > + return expr_to_aff_combination (comb, icode, otype, op0, > > > op1, > > > + at, query); > > > } > > > wide_int minv, maxv; > > > /* If inner type has wrapping overflow behavior, fold > > > conversion > > > @@ -346,10 +442,12 @@ expr_to_aff_combination (aff_tree *comb, tree_code > > > code, tree type, > > > (T1)(X *+- CST) -> (T1)X *+- (T1)CST > > > if X *+- CST doesn't overflow by range information. */ > > > int_range_max vr; > > > + if (!rquery) > > > + rquery = get_range_query (cfun); > > > if (TYPE_UNSIGNED (itype) > > > && TYPE_OVERFLOW_WRAPS (itype) > > > && TREE_CODE (op1) == INTEGER_CST > > > - && get_range_query (cfun)->range_of_expr (vr, op0) > > > + && rquery->range_of_expr (vr, op0, at) > > > && !vr.varying_p () > > > && !vr.undefined_p ()) > > > { > > > @@ -369,7 +467,24 @@ expr_to_aff_combination (aff_tree *comb, tree_code > > > code, tree type, > > > op0 = fold_convert (otype, op0); > > > op1 = fold_convert (otype, op1); > > > return expr_to_aff_combination (comb, icode, otype, > > > op0, > > > - op1); > > > + op1, at, query); > > > + } > > > + else if (icode == PLUS_EXPR > > > + && wi::neg_p (wi::to_wide (op1), SIGNED)) > > > + { > > > + wide_int pos_cst = wi::neg (wi::to_wide (op1)); > > > + > > > + /* X + CST in the wrapping type is X - -CST when X is > > > + known to be at least -CST. */ > > > + if (wi::geu_p (minv, pos_cst)) > > > + { > > > + op0 = fold_convert (otype, op0); > > > + op1 = fold_convert (otype, > > > + wide_int_to_tree (itype, > > > pos_cst)); > > > + return expr_to_aff_combination (comb, MINUS_EXPR, > > > + otype, op0, op1, > > > at, > > > + query); > > > + } > > > } > > > } > > > } > > > @@ -385,7 +500,8 @@ 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, gimple > > > *at, > > > + range_query *query) > > > { > > > aff_tree tmp; > > > enum tree_code code; > > > @@ -404,13 +520,14 @@ tree_to_aff_combination (tree expr, tree type, > > > aff_tree *comb) > > > case MINUS_EXPR: > > > case MULT_EXPR: > > > if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, > > > 0), > > > - TREE_OPERAND (expr, 1))) > > > + TREE_OPERAND (expr, 1), at, query)) > > > return; > > > break; > > > > > > case NEGATE_EXPR: > > > case BIT_NOT_EXPR: > > > - if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, > > > 0))) > > > + if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, > > > 0), > > > + NULL_TREE, at, query)) > > > return; > > > break; > > > > > > @@ -418,7 +535,8 @@ tree_to_aff_combination (tree expr, tree type, > > > aff_tree *comb) > > > /* ??? 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))) > > > + TREE_TYPE (expr), TREE_OPERAND (expr, > > > 0), > > > + NULL_TREE, at, query)) > > > { > > > aff_combination_convert (comb, type); > > > return; > > > @@ -430,8 +548,10 @@ tree_to_aff_combination (tree expr, tree type, > > > aff_tree *comb) > > > 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); > > > + tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb, at, > > > + query); > > > + tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp, > > > + at, query); > > > aff_combination_add (comb, &tmp); > > > return; > > > } > > > @@ -454,12 +574,12 @@ tree_to_aff_combination (tree expr, tree type, > > > aff_tree *comb) > > > aff_combination_add_elt (comb, core, 1); > > > else > > > { > > > - tree_to_aff_combination (core, type, &tmp); > > > + tree_to_aff_combination (core, type, &tmp, at, query); > > > aff_combination_add (comb, &tmp); > > > } > > > if (toffset) > > > { > > > - tree_to_aff_combination (toffset, type, &tmp); > > > + tree_to_aff_combination (toffset, type, &tmp, at, query); > > > aff_combination_add (comb, &tmp); > > > } > > > return; > > > diff --git a/gcc/tree-affine.h b/gcc/tree-affine.h > > > index 38d32ef1b4b..8ea648f0f1b 100644 > > > --- a/gcc/tree-affine.h > > > +++ b/gcc/tree-affine.h > > > @@ -65,6 +65,7 @@ public: > > > }; > > > > > > class name_expansion; > > > +class range_query; > > > > > > void aff_combination_const (aff_tree *, tree, const poly_widest_int &); > > > void aff_combination_elt (aff_tree *, tree, tree); > > > @@ -74,7 +75,8 @@ 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 tree_to_aff_combination (tree, tree, aff_tree *, gimple * = NULL, > > > + range_query * = NULL); > > > tree aff_combination_to_tree (aff_tree *); > > > void unshare_aff_combination (aff_tree *); > > > bool aff_combination_constant_multiple_p (aff_tree *, aff_tree *, > > > diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc > > > index 5a4254290d8..f70d39cd978 100644 > > > --- a/gcc/tree-ssa-loop-ivopts.cc > > > +++ b/gcc/tree-ssa-loop-ivopts.cc > > > @@ -133,6 +133,7 @@ along with GCC; see the file COPYING3. If not see > > > #include "dbgcnt.h" > > > #include "cfganal.h" > > > #include "gimple-fold.h" > > > +#include "gimple-range.h" > > > > > > /* For lang_hooks.types.type_for_mode. */ > > > #include "langhooks.h" > > > @@ -620,6 +621,9 @@ struct ivopts_data > > > /* Cache used by tree_to_aff_combination_expand. */ > > > hash_map<tree, name_expansion *> *name_expansion_cache; > > > > > > + /* Range query for statement-local affine simplifications. */ > > > + range_query *ranger; > > > + > > > /* The hashtable of common candidates derived from iv uses. */ > > > hash_table<iv_common_cand_hasher> *iv_common_cand_tab; > > > > > > @@ -1086,6 +1090,7 @@ tree_ssa_iv_optimize_init (struct ivopts_data *data) > > > data->vcands.create (20); > > > data->inv_expr_tab = new hash_table<iv_inv_expr_hasher> (10); > > > data->name_expansion_cache = NULL; > > > + data->ranger = NULL; > > > data->base_object_map = NULL; > > > data->iv_common_cand_tab = new hash_table<iv_common_cand_hasher> (10); > > > data->iv_common_cands.create (20); > > > @@ -4037,9 +4042,11 @@ get_computation_aff_1 (struct ivopts_data *data, > > > gimple *at, struct iv_use *use, > > > common_type = determine_common_wider_type (&ubase, &cbase); > > > > > > /* use = ubase - ratio * cbase + ratio * var. */ > > > - tree_to_aff_combination (ubase, common_type, aff_inv); > > > - tree_to_aff_combination (cbase, common_type, &aff_cbase); > > > - tree_to_aff_combination (var, uutype, aff_var); > > > + tree_to_aff_combination (ubase, common_type, aff_inv, at, > > > + data->ranger); > > > + tree_to_aff_combination (cbase, common_type, &aff_cbase, at, > > > + data->ranger); > > > + tree_to_aff_combination (var, uutype, aff_var, at, data->ranger); > > > > > > /* We need to shift the value if we are after the increment. */ > > > if (stmt_after_increment (data->current_loop, cand, at)) > > > @@ -4051,7 +4058,8 @@ get_computation_aff_1 (struct ivopts_data *data, > > > gimple *at, struct iv_use *use, > > > else > > > cstep_common = cstep; > > > > > > - tree_to_aff_combination (cstep_common, common_type, &cstep_aff); > > > + tree_to_aff_combination (cstep_common, common_type, &cstep_aff, at, > > > + data->ranger); > > > aff_combination_add (&aff_cbase, &cstep_aff); > > > } > > > > > > @@ -5105,6 +5113,8 @@ cand_value_at (class loop *loop, struct iv_cand > > > *cand, gimple *at, > > > } > > > } > > > > > > + /* The result may be materialized in the loop preheader. Do not use > > > range > > > + information that is only valid at AT when simplifying it. */ > > > tree_to_aff_combination (iv->step, TREE_TYPE (iv->step), &step); > > > aff_combination_convert (&step, steptype); > > > tree_to_aff_combination (niter, TREE_TYPE (niter), &nit); > > > @@ -8245,6 +8255,8 @@ tree_ssa_iv_optimize (void) > > > > > > tree_ssa_iv_optimize_init (&data); > > > mark_ssa_maybe_undefs (); > > > + gimple_ranger ranger (false); > > > + data.ranger = &ranger; > > > > > > /* Optimize the loops starting with the innermost ones. */ > > > for (auto loop : loops_list (cfun, LI_FROM_INNERMOST)) > > > -- > > > 2.34.1 > > > > > > > -- > BR, > Hongtao
