On Thu, Sep 4, 2025 at 3:08 AM Andrew Pinski <[email protected]> wrote: > > 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.
OK. Thanks, Richard. > 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 <[email protected]> > --- > .../tree-ssa/copy-prop-aggregate-union-1.c | 24 ++++++++++++ > gcc/tree-ssa-forwprop.cc | 37 ++++++++++++++++++- > 2 files changed, 60 insertions(+), 1 deletion(-) > create mode 100644 > gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-union-1.c > > 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 00000000000..206f6e1be55 > --- /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 df876f7db0a..59b1878a68f 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)) > { > -- > 2.43.0 >
