From: Kugan Vivekanandarajah Date: Mon, 22 Dec 2025 21:28:54 +0000 (+1100) Subject: [Bug 123067][V3] Fix LICM wrong code X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ee4a808fdab1b7a83636a64dff633b0bff849629;p=thirdparty%2Fgcc.git [Bug 123067][V3] Fix LICM wrong code Check for partial aliasing in self write test. gcc/ChangeLog: 2025-12-22 Kugan Vivekanandarajah 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 PR middle-end/123067 * gcc.dg/licm-self-write-partial-alias.c: New test. Signed-off-by: Kugan Vivekanandarajah --- 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 00000000000..7b8792feb75 --- /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 61f08beb9ff..35628befc50 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. */