Thank you for your review and suggestions.

Richard Biener <[email protected]> 于2026年6月19日周五 19:29写道:

> On Wed, 20 May 2026, Xin Wang wrote:
>
> > Restructure mem_ref_hasher::equal so the non-decomposed fallback
> > and the decomposed comparison path are explicit. The non-decomposed
> > lookup still compares the original refs with operand_equal_p, while
> > the decomposed path keeps the same base, offset, size, max_size,
> > volatile, alias-set, and type checks as before. This matches the split
> > in gather_mem_refs_stmt, where non-decomposed references are marked
> > with an unknown max_size and decomposed references are hashed from
> > base, offset, and size.
>
> Thanks for doing this, this is OK and I'm going to push it
> momentarily.
>
> Sorry for the delay,
> Richard.
>
> > Signed-off-by: Xin Wang <[email protected]>
> > ---
> >  gcc/tree-ssa-loop-im.cc | 64 +++++++++++++++++++++++------------------
> >  1 file changed, 36 insertions(+), 28 deletions(-)
> >
> > diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
> > index 2651e3919e3..1e99728218f 100644
> > --- a/gcc/tree-ssa-loop-im.cc
> > +++ b/gcc/tree-ssa-loop-im.cc
> > @@ -202,34 +202,43 @@ mem_ref_hasher::hash (const im_mem_ref *mem)
> >  inline bool
> >  mem_ref_hasher::equal (const im_mem_ref *mem1, const ao_ref *obj2)
> >  {
> > -  if (obj2->max_size_known_p ())
> > -    return (mem1->ref_decomposed
> > -         && ((TREE_CODE (mem1->mem.base) == MEM_REF
> > -              && TREE_CODE (obj2->base) == MEM_REF
> > -              && operand_equal_p (TREE_OPERAND (mem1->mem.base, 0),
> > -                                  TREE_OPERAND (obj2->base, 0), 0)
> > -              && known_eq (mem_ref_offset (mem1->mem.base) *
> BITS_PER_UNIT + mem1->mem.offset,
> > -                           mem_ref_offset (obj2->base) * BITS_PER_UNIT
> + obj2->offset))
> > -             || (operand_equal_p (mem1->mem.base, obj2->base, 0)
> > -                 && known_eq (mem1->mem.offset, obj2->offset)))
> > -         && known_eq (mem1->mem.size, obj2->size)
> > -         && known_eq (mem1->mem.max_size, obj2->max_size)
> > -         && mem1->mem.volatile_p == obj2->volatile_p
> > -         && (mem1->mem.ref_alias_set == obj2->ref_alias_set
> > -             /* We are not canonicalizing alias-sets but for the
> > -                special-case we didn't canonicalize yet and the
> > -                incoming ref is a alias-set zero MEM we pick
> > -                the correct one already.  */
> > -             || (!mem1->ref_canonical
> > -                 && (TREE_CODE (obj2->ref) == MEM_REF
> > -                     || TREE_CODE (obj2->ref) == TARGET_MEM_REF)
> > -                 && obj2->ref_alias_set == 0)
> > -             /* Likewise if there's a canonical ref with alias-set
> zero.  */
> > -             || (mem1->ref_canonical && mem1->mem.ref_alias_set == 0))
> > -         && types_compatible_p (TREE_TYPE (mem1->mem.ref),
> > -                                TREE_TYPE (obj2->ref)));
> > -  else
> > +  if (!obj2->max_size_known_p ())
> >      return operand_equal_p (mem1->mem.ref, obj2->ref, 0);
> > +
> > +  if (!mem1->ref_decomposed)
> > +    return false;
> > +
> > +  /* obj2 is now known decomposable and the hash is based on offset,
> > +     size and base, matching gather_mem_refs_stmt.  */
> > +  bool refs_equal
> > +    = ((TREE_CODE (mem1->mem.base) == MEM_REF
> > +     && TREE_CODE (obj2->base) == MEM_REF
> > +     && operand_equal_p (TREE_OPERAND (mem1->mem.base, 0),
> > +                         TREE_OPERAND (obj2->base, 0), 0)
> > +     && known_eq (mem_ref_offset (mem1->mem.base) * BITS_PER_UNIT
> > +                  + mem1->mem.offset,
> > +                  mem_ref_offset (obj2->base) * BITS_PER_UNIT
> > +                  + obj2->offset))
> > +       || (operand_equal_p (mem1->mem.base, obj2->base, 0)
> > +        && known_eq (mem1->mem.offset, obj2->offset)));
> > +
> > +  return (refs_equal
> > +       && known_eq (mem1->mem.size, obj2->size)
> > +       && known_eq (mem1->mem.max_size, obj2->max_size)
> > +       && mem1->mem.volatile_p == obj2->volatile_p
> > +       && (mem1->mem.ref_alias_set == obj2->ref_alias_set
> > +           /* We are not canonicalizing alias-sets but for the
> > +              special-case we didn't canonicalize yet and the
> > +              incoming ref is a alias-set zero MEM we pick
> > +              the correct one already.  */
> > +           || (!mem1->ref_canonical
> > +               && (TREE_CODE (obj2->ref) == MEM_REF
> > +                   || TREE_CODE (obj2->ref) == TARGET_MEM_REF)
> > +               && obj2->ref_alias_set == 0)
> > +           /* Likewise if there's a canonical ref with alias-set zero.
> */
> > +           || (mem1->ref_canonical && mem1->mem.ref_alias_set == 0))
> > +       && types_compatible_p (TREE_TYPE (mem1->mem.ref),
> > +                              TREE_TYPE (obj2->ref)));
> >  }
> >
> >
> > @@ -3875,4 +3884,3 @@ make_pass_lim (gcc::context *ctxt)
> >    return new pass_lim (ctxt);
> >  }
> >
> > -
> >
>
> --
> Richard Biener <[email protected]>
> SUSE Software Solutions Germany GmbH,
> Frankenstrasse 146, 90461 Nuernberg, Germany;
> GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG
> Nuernberg)
>

Reply via email to