Hi, we currently use the types encountered in the function body and not in type declaration to perform total scalarization. Bug PR 119085 uncovered that we miss a check that when the same data is accessed with aggregate types that those are actually compatible. Without it, we can base total scalarization on a type that does not "cover" all live data in a different part of the function. This patch adds the check.
Bootstrapped and tested on x86_64-linux. OK for master and all active release branches? Thanks, Martin gcc/ChangeLog: 2025-07-21 Martin Jambor <mjam...@suse.cz> PR tree-optimization/119085 * tree-sra.cc (sort_and_splice_var_accesses): Prevent total scalarization if two incompatible aggregates access the same place. gcc/testsuite/ChangeLog: 2025-07-21 Martin Jambor <mjam...@suse.cz> PR tree-optimization/119085 * gcc.dg/tree-ssa/pr119085.c: New test. --- gcc/testsuite/gcc.dg/tree-ssa/pr119085.c | 37 ++++++++++++++++++++++++ gcc/tree-sra.cc | 6 ++++ 2 files changed, 43 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr119085.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr119085.c b/gcc/testsuite/gcc.dg/tree-ssa/pr119085.c new file mode 100644 index 00000000000..e9811ce12b5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr119085.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +struct with_hole { + int x; + long y; +}; +struct without_hole { + int x; + int y; +}; +union u { + struct with_hole with_hole; + struct without_hole without_hole; +}; + +void __attribute__((noinline)) +test (union u *up, union u u) +{ + union u u2; + volatile int f = 0; + u2 = u; + if (f) + u2.with_hole = u.with_hole; + *up = u2; +} + +int main(void) +{ + union u u; + union u u2; + u2.without_hole.y = -1; + test (&u, u2); + if (u.without_hole.y != -1) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc index 240af676ea3..032f2770484 100644 --- a/gcc/tree-sra.cc +++ b/gcc/tree-sra.cc @@ -2504,6 +2504,12 @@ sort_and_splice_var_accesses (tree var) } unscalarizable_region = true; } + /* If there the same place is accessed with two incompatible + aggregate types, trying to base total scalarization on either of + them can be wrong. */ + if (!first_scalar && !types_compatible_p (access->type, ac2->type)) + bitmap_set_bit (cannot_scalarize_away_bitmap, + DECL_UID (access->base)); if (grp_same_access_path && (!ac2->grp_same_access_path -- 2.50.1