]> git.feebdaed.xyz Git - 0xmirror/gcc.git/commitdiff
[Bug 123067][V3] Fix LICM wrong code
authorKugan Vivekanandarajah <kvivekananda@nvidia.com>
Mon, 22 Dec 2025 21:28:54 +0000 (08:28 +1100)
committerKugan Vivekanandarajah <kvivekananda@nvidia.com>
Mon, 22 Dec 2025 21:28:54 +0000 (08:28 +1100)
Check for partial aliasing in self write test.

gcc/ChangeLog:

2025-12-22  Kugan Vivekanandarajah  <kvivekananda@nvidia.com>

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  <kvivekananda@nvidia.com>

PR middle-end/123067
* gcc.dg/licm-self-write-partial-alias.c: New test.

Signed-off-by: Kugan Vivekanandarajah <kvivekananda@nvidia.com>
gcc/testsuite/gcc.dg/licm-self-write-partial-alias.c [new file with mode: 0644]
gcc/tree-ssa-loop-im.cc

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 (file)
index 0000000..7b8792f
--- /dev/null
@@ -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;
+}
+
index 61f08beb9ff6c0a5175c4317be9724b90855a6ce..35628befc502aff38c1afe4d1e4a132542000d46 100644 (file)
@@ -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.  */