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.
>
> > +
> > +                   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

Reply via email to