aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>2025-08-26 22:04:06 -0700
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>2025-09-04 03:12:43 -0700
commitadfe96eb612feeb6abb2ecac267325243039a0f8 (patch)
treefd42566b6788d38a19eb0916796000582a49931b
parent43a8c0f8e67f282823a3af1df4cd77dd86981b9c (diff)
downloadgcc-adfe96eb612feeb6abb2ecac267325243039a0f8.zip
gcc-adfe96eb612feeb6abb2ecac267325243039a0f8.tar.gz
gcc-adfe96eb612feeb6abb2ecac267325243039a0f8.tar.bz2
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.pinski@oss.qualcomm.com>
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-union-1.c24
-rw-r--r--gcc/tree-ssa-forwprop.cc37
2 files changed, 60 insertions, 1 deletions
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 0000000..206f6e1
--- /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 df876f7..59b1878 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))
{