diff options
author | Richard Biener <rguenther@suse.de> | 2025-09-03 12:54:58 +0200 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2025-09-04 10:03:32 +0200 |
commit | 95afbe4c7633459b59d434550888decc41b4d44f (patch) | |
tree | 597bdae49cffdc7fecd8ceb4cd456a9885b78c90 /gcc | |
parent | b26033d579a9df55f38f3b9ff8400c21f2a5717d (diff) | |
download | gcc-95afbe4c7633459b59d434550888decc41b4d44f.zip gcc-95afbe4c7633459b59d434550888decc41b4d44f.tar.gz gcc-95afbe4c7633459b59d434550888decc41b4d44f.tar.bz2 |
tree-optimization/121740 - handle aggregate zeroing as skipped may-def
The following makes value-numbering handle a situation like
D.58046 = {};
SR.83_44->i = {};
pretmp_41 = MEM[(struct _Optional_payload_base &)&D.58046 + 8]._M_engaged;
where the intermediate may-def SR.83_44->i = {} prevents CSE of the
load to zero. The problem is two-fold here, one is that the code
skipping may-defs does not handle zeroing via a CTOR, the other is that
(partial) must-defs can be better handled by later code as otherwise
we may not find an appropriate definition to CSE to.
I've noticed we fail to guard against storage-order issues, so fixed
that on the fly.
PR tree-optimization/121740
* tree-ssa-sccvn.cc (vn_reference_lookup_3): Allow skipping
may-defs from CTORs. Do not skip may-defs with storage-order
issues or (partial) must-defs.
* gcc.dg/tree-ssa/ssa-fre-104.c: Un-XFAIL.
* gcc.dg/tree-ssa/ssa-fre-110.c: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-104.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-110.c | 15 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.cc | 33 |
3 files changed, 47 insertions, 3 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-104.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-104.c index 52756bb..8c9df70 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-104.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-104.c @@ -21,4 +21,4 @@ int main() { *c = &d; } -/* { dg-final { scan-tree-dump-not "foo" "fre1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-not "foo" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-110.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-110.c new file mode 100644 index 0000000..10e391d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-110.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1-details" } */ + +struct A { int x; int y; }; +struct B { struct A a; int k; }; + +int foo (struct A *a, struct B *b) +{ + *a = (struct A){}; + *b = (struct B){}; + return a->x; +} + +/* { dg-final { scan-tree-dump "Skipping possible redundant definition" "fre1" } } */ +/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */ diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 3884f0f..3212063 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -2810,8 +2810,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, possible clobber. In this case we can ignore the clobber and return the found value. */ if (!gimple_has_volatile_ops (def_stmt) - && is_gimple_reg_type (TREE_TYPE (lhs)) - && types_compatible_p (TREE_TYPE (lhs), vr->type) + && ((is_gimple_reg_type (TREE_TYPE (lhs)) + && types_compatible_p (TREE_TYPE (lhs), vr->type) + && !storage_order_barrier_p (lhs) + && !reverse_storage_order_for_component_p (lhs)) + || TREE_CODE (gimple_assign_rhs1 (def_stmt)) == CONSTRUCTOR) && (ref->ref || data->orig_ref.ref) && !data->mask && data->partial_defs.is_empty () @@ -2820,7 +2823,19 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, ref->size) && multiple_p (get_object_alignment (lhs), ref->size)) { + HOST_WIDE_INT offset2i, size2i; + poly_int64 offset = ref->offset; + poly_int64 maxsize = ref->max_size; + + gcc_assert (lhs_ref_ok); + tree base2 = ao_ref_base (&lhs_ref); + poly_int64 offset2 = lhs_ref.offset; + poly_int64 size2 = lhs_ref.size; + poly_int64 maxsize2 = lhs_ref.max_size; + tree rhs = gimple_assign_rhs1 (def_stmt); + if (TREE_CODE (rhs) == CONSTRUCTOR) + rhs = integer_zero_node; /* ??? We may not compare to ahead values which might be from a different loop iteration but only to loop invariants. Use CONSTANT_CLASS_P (unvalueized!) as conservative approximation. @@ -2831,6 +2846,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, if (data->same_val && !operand_equal_p (data->same_val, rhs)) ; + /* When this is a (partial) must-def, leave it to handling + below in case we are interested in the value. */ + else if (!(*disambiguate_only > TR_TRANSLATE) + && base2 + && known_eq (maxsize2, size2) + && adjust_offsets_for_equal_base_address (base, &offset, + base2, &offset2) + && offset2.is_constant (&offset2i) + && size2.is_constant (&size2i) + && maxsize.is_constant (&maxsizei) + && offset.is_constant (&offseti) + && ranges_known_overlap_p (offseti, maxsizei, offset2i, + size2i)) + ; else if (CONSTANT_CLASS_P (rhs)) { if (dump_file && (dump_flags & TDF_DETAILS)) |