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

commit r16-3567-gadfe96eb612feeb6abb2ecac267325243039a0f8
Author: Andrew Pinski <andrew.pin...@oss.qualcomm.com>
Date:   Tue Aug 26 22:04:06 2025 -0700

    forwprop: Improve the reject case for copy prop [PR107051]
    
    Currently the code rejects:
    ```
    tmp = *a;
    *b = tmp;
    ```
    (unless *a == *b). This can be improved such that if a and b are known to
    share the same base, then only reject it if they overlap; that is the
    difference of the offsets (from the base) is maybe less than the size.
    
    This fixes the testcase in comment #0 of PR 107051.
    
    Changes since v1:
    * v2: Use ranges_maybe_overlap_p instead of manually checking the overlap.
          Allow for the case where the alignment is known to be greater than
          the size.
    
            PR tree-optimization/107051
    
    gcc/ChangeLog:
    
            * tree-ssa-forwprop.cc (optimize_agr_copyprop_1): Allow for
            memory sharing the same base if they known not to overlap over
            the size.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/copy-prop-aggregate-union-1.c: New test.
    
    Signed-off-by: Andrew Pinski <andrew.pin...@oss.qualcomm.com>

Diff:
---
 .../gcc.dg/tree-ssa/copy-prop-aggregate-union-1.c  | 24 ++++++++++++++
 gcc/tree-ssa-forwprop.cc                           | 37 +++++++++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-union-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-union-1.c
new file mode 100644
index 000000000000..206f6e1be550
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-union-1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-forwprop1-details" } */
+/* PR tree-optimization/107051 */
+
+
+union U2 {
+   unsigned  f0;
+   char * f1;
+};
+
+/* Since g_284[0] and g_284[1] are known not overlap,
+   copy prop can happen.  */
+union U2 g_284[2] = {{0UL},{0xC2488F72L}};
+
+int e;
+void func_1() {
+       union U2 c = {7};
+       int *d[2];
+       for (; e;)
+               *d[1] = 0;
+       g_284[0] = c = g_284[1];
+}
+
+/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index df876f7db0a0..59b1878a68f1 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -1455,7 +1455,42 @@ optimize_agr_copyprop_1 (gimple *stmt, gimple *use_stmt,
      */
   if (!operand_equal_p (dest2, src, 0)
       && !DECL_P (dest2) && !DECL_P (src))
-    return false;
+    {
+      /* If *a and *b have the same base see if
+        the offset between the two is greater than
+        or equal to the size of the type. */
+      poly_int64 offset1, offset2;
+      tree len = TYPE_SIZE_UNIT (TREE_TYPE (src));
+      if (len == NULL_TREE
+         || !tree_fits_poly_int64_p (len))
+       return false;
+      tree base1 = get_addr_base_and_unit_offset (dest2, &offset1);
+      tree base2 = get_addr_base_and_unit_offset (src, &offset2);
+      poly_int64 size = tree_to_poly_int64 (len);
+      /* If we can't figure out the base or the bases are
+        not equal then fall back to an alignment check.  */
+      if (!base1
+         || !base2
+         || !operand_equal_p (base1, base2))
+       {
+         unsigned int align1 = get_object_alignment (src);
+         unsigned int align2 = get_object_alignment (dest2);
+         align1 /= BITS_PER_UNIT;
+         align2 /= BITS_PER_UNIT;
+         /* If the alignment of either object is less
+            than the size then there is a possibility
+            of overlapping.  */
+         if (maybe_lt (align1, size)
+             || maybe_lt (align2, size))
+           return false;
+       }
+      /* Make sure [offset1, offset1 + len - 1] does
+        not overlap with [offset2, offset2 + len - 1],
+        it is ok if they are at the same location though.  */
+      else if (ranges_maybe_overlap_p (offset1, size, offset2, size)
+         && !known_eq (offset2, offset1))
+       return false;
+    }
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {

Reply via email to