diff options
author | Andrew Pinski <andrew.pinski@oss.qualcomm.com> | 2025-08-26 22:04:06 -0700 |
---|---|---|
committer | Andrew Pinski <andrew.pinski@oss.qualcomm.com> | 2025-09-04 03:12:43 -0700 |
commit | adfe96eb612feeb6abb2ecac267325243039a0f8 (patch) | |
tree | fd42566b6788d38a19eb0916796000582a49931b | |
parent | 43a8c0f8e67f282823a3af1df4cd77dd86981b9c (diff) | |
download | gcc-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.c | 24 | ||||
-rw-r--r-- | gcc/tree-ssa-forwprop.cc | 37 |
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)) { |