aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2025-09-03 12:54:58 +0200
committerRichard Biener <rguenth@gcc.gnu.org>2025-09-04 10:03:32 +0200
commit95afbe4c7633459b59d434550888decc41b4d44f (patch)
tree597bdae49cffdc7fecd8ceb4cd456a9885b78c90 /gcc
parentb26033d579a9df55f38f3b9ff8400c21f2a5717d (diff)
downloadgcc-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.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-110.c15
-rw-r--r--gcc/tree-ssa-sccvn.cc33
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))