https://gcc.gnu.org/g:ee4a808fdab1b7a83636a64dff633b0bff849629

commit r16-6340-gee4a808fdab1b7a83636a64dff633b0bff849629
Author: Kugan Vivekanandarajah <[email protected]>
Date:   Tue Dec 23 08:28:54 2025 +1100

    [Bug 123067][V3] Fix LICM wrong code
    
    Check for partial aliasing in self write test.
    
    gcc/ChangeLog:
    
    2025-12-22  Kugan Vivekanandarajah  <[email protected]>
    
            PR middle-end/123067
            * tree-ssa-loop-im.cc(is_self_write): Check
            load and store refer to same location.
    
    gcc/testsuite/ChangeLog:
    
    2025-12-22  Kugan Vivekanandarajah  <[email protected]>
    
            PR middle-end/123067
            * gcc.dg/licm-self-write-partial-alias.c: New test.
    
    Signed-off-by: Kugan Vivekanandarajah <[email protected]>

Diff:
---
 .../gcc.dg/licm-self-write-partial-alias.c         | 31 ++++++++++++++++++++++
 gcc/tree-ssa-loop-im.cc                            | 22 ++++++++++++++-
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/licm-self-write-partial-alias.c 
b/gcc/testsuite/gcc.dg/licm-self-write-partial-alias.c
new file mode 100644
index 000000000000..7b8792feb754
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/licm-self-write-partial-alias.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int
+main (void)
+{
+  /* Array element shifting - partial aliasing.  */
+  {
+    int a[6] = {0, 0, 1, 2, 0, 0};
+    unsigned char i, j;
+    for (i = 1; i != 0; ++i)
+      {
+        for (j = 1; j <= 4; j++)
+          a[j] = a[j + 1];
+      }
+    if (a[1] != 0)
+      __builtin_abort ();
+  }
+
+  /* Memmove with overlapping regions - partial aliasing.  */
+  {
+    unsigned char a[6] = {0, 0, 1, 2, 0, 0};
+    for (int i = 0; i < 256; i++)
+      __builtin_memmove (&a[1], &a[2], 4);
+    if (a[1] != 0)
+      __builtin_abort ();
+  }
+
+  return 0;
+}
+
diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
index 61f08beb9ff6..35628befc502 100644
--- a/gcc/tree-ssa-loop-im.cc
+++ b/gcc/tree-ssa-loop-im.cc
@@ -3174,7 +3174,27 @@ is_self_write (im_mem_ref *load_ref, im_mem_ref 
*store_ref)
     return false;
 
   /* Self write: stored value is the loaded value.  */
-  return stored_val == loaded_val;
+  if (stored_val != loaded_val)
+    return false;
+
+
+  /* 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));
+
 }
 
 /* Returns true if REF1 and REF2 are independent.  */

Reply via email to