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)) {