[PATCH] LICM: Factor out memory reference comparison into helper
Xin Wang
yw987194828@gmail.com
Fri Jan 30 12:40:19 GMT 2026
From: Xin Wang <wangxinw@hygon.cn>
This patch centralizes the delicate handling of MEM_REF offsets and base
pointer equality into a new helper function im_compare_access_position_and
_size, which is now used by both mem_ref_hasher::equal and is_self_write.
gcc/ChangeLog:
* tree-ssa-loop-im.cc (im_compare_access_position_and_size): New helper
function to compare ao_ref position and size. (mem_ref_hasher::equal):
Use the new helper for position and size comparison, keeping additional
hash table specific checks. (is_self_write): Likewise, using the
centralized helper after checking ref_decomposed.
Signed-off-by: Xin Wang <wangxinw@hygon.cn>
---
gcc/tree-ssa-loop-im.cc | 114 +++++++++++++++++++++++++---------------
1 file changed, 73 insertions(+), 41 deletions(-)
diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
index 72e19981698..74fe47e8cda 100644
--- a/gcc/tree-ssa-loop-im.cc
+++ b/gcc/tree-ssa-loop-im.cc
@@ -180,6 +180,50 @@ query_loop_dependence (class loop *loop, im_mem_ref *ref, dep_kind kind)
return dep_unknown;
}
+/* Returns true if the positions and sizes of two ao_ref structures are
+ equal. This handles MEM_REF offsets specially by merging the offset
+ from the MEM_REF base with the ao_ref offset.
+
+ This helper centralizes the delicate handling of memory reference
+ comparison, used by both mem_ref_hasher::equal and is_self_write. */
+
+static bool
+im_compare_access_position_and_size (const ao_ref *ref1, const ao_ref *ref2)
+{
+ /* Check base pointer equality. For MEM_REF types, we need to
+ compare the underlying pointer operands and merge the offsets. */
+ if (TREE_CODE (ref1->base) == MEM_REF && TREE_CODE (ref2->base) == MEM_REF)
+ {
+ if (!operand_equal_p (TREE_OPERAND (ref1->base, 0),
+ TREE_OPERAND (ref2->base, 0), 0))
+ return false;
+
+ /* Both are MEM_REF - compare merged offsets from base and offset. */
+ if (!known_eq (mem_ref_offset (ref1->base) * BITS_PER_UNIT
+ + ref1->offset,
+ mem_ref_offset (ref2->base) * BITS_PER_UNIT
+ + ref2->offset))
+ return false;
+ }
+ else if (!operand_equal_p (ref1->base, ref2->base, 0)
+ || !known_eq (ref1->offset, ref2->offset))
+ return false;
+
+ /* Compare sizes. */
+ if (!known_eq (ref1->size, ref2->size))
+ return false;
+
+ /* If both max_sizes are known, they must agree to ensure
+ no partial overlaps are possible. */
+ if (ref1->max_size_known_p () && ref2->max_size_known_p ())
+ {
+ if (!known_eq (ref1->max_size, ref2->max_size))
+ return false;
+ }
+
+ return true;
+}
+
/* Mem_ref hashtable helpers. */
struct mem_ref_hasher : nofree_ptr_hash <im_mem_ref>
@@ -204,31 +248,30 @@ 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)));
+ {
+ if (!mem1->ref_decomposed)
+ return false;
+
+ /* Use the centralized helper for position and size comparison. */
+ if (!im_compare_access_position_and_size (&mem1->mem, obj2))
+ return false;
+
+ /* Additional checks specific to hash table lookup. */
+ return (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
return operand_equal_p (mem1->mem.ref, obj2->ref, 0);
}
@@ -3177,23 +3220,12 @@ is_self_write (im_mem_ref *load_ref, im_mem_ref *store_ref)
if (stored_val != loaded_val)
return false;
+ /* They may alias. Verify exact same location.
+ Use the centralized helper to handle MEM_REF offsets properly. */
+ if (!load_ref->ref_decomposed || !store_ref->ref_decomposed)
+ return operand_equal_p (load_ref->mem.ref, store_ref->mem.ref, 0);
- /* TODO: Try to factor this out with mem_ref_hasher::equal
- into im_compare_access_position_and_size
- or a similar helper to centralize this delicate handling
- complete for MEM_REF offsets and base pointer equality.
-
- TODO: Also ensure max_size_known_p agrees or resort to
- alignment considerations to rule out partial overlaps.
-
- See:
- https://gcc.gnu.org/pipermail/gcc-patches/2025-December/704155.html
- For more context on TODOs above. */
-
- /* They may alias. Verify exact same location. */
- return (operand_equal_p (load_ref->mem.base, store_ref->mem.base, 0)
- && known_eq (load_ref->mem.size, store_ref->mem.size)
- && known_eq (load_ref->mem.offset, store_ref->mem.offset));
+ return im_compare_access_position_and_size (&load_ref->mem, &store_ref->mem);
}
--
2.34.1
More information about the Gcc-patches
mailing list