On Thu, 17 Jul 2025, Martin Jambor wrote:

> Hi,
> 
> testcase of PR 117423 shows a flaw in the fancy way we do "total
> scalarization" in SRA now.  We use the types encountered in the
> function body and not in type declaration (allowing us to totally
> scalarize when only one union field is ever used, since we effectively
> "skip" the union then) and can accommodate pre-existing accesses that
> happen to fall into padding.
> 
> In this case, we skipped the union (bypassing the
> totally_scalarizable_type_p check) and the access falling into the
> "padding" is an aggregate and so not a candidate for SRA but actually
> containing data.  Arguably total scalarization should just bail out
> when it encounters this situation (but I decided not to depend on this
> mainly because we'd need to detect all cases when we eventually cannot
> scalarize, such as when a scalar access has children accesses) but the
> actual bug is that the detection if all data in an aggregate is indeed
> covered by replacements just assumes that is always the case if total
> scalarization triggers which however may not be the case in cases like
> this - and perhaps more.
> 
> This patch fixes the bug by just assuming that all padding is taken
> care of when total scalarization triggered, not that every access was
> actually scalarized.
> 
> Bootstrapped and tested on x86_64-linux, I'm also running a bootstrap
> and testing on aarch64-linux as I'm writing this but will know the
> results only tomorrow.  OK for master and later for all active release
> branches if it passes there too?

OK.

Thanks,
Richard.

> Thanks,
> 
> Martin
> 
> 
> gcc/ChangeLog:
> 
> 2025-07-17  Martin Jambor  <mjam...@suse.cz>
> 
>       PR tree-optimization/117423
>       * tree-sra.cc (analyze_access_subtree): Fix computation of grp_covered
>       flag.
> 
> gcc/testsuite/ChangeLog:
> 
> 2025-07-17  Martin Jambor  <mjam...@suse.cz>
> 
>       PR tree-optimization/117423
>       * gcc.dg/tree-ssa/pr117423.c: New test.
> ---
>  gcc/testsuite/gcc.dg/tree-ssa/pr117423.c | 49 ++++++++++++++++++++++++
>  gcc/tree-sra.cc                          |  9 ++++-
>  2 files changed, 56 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr117423.c
> 
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr117423.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr117423.c
> new file mode 100644
> index 00000000000..a5d3b29886f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr117423.c
> @@ -0,0 +1,49 @@
> +/* { dg-do run } */
> +/* { dg-options "-O1" } */
> +
> +struct s4 {
> +    int _0;
> +};
> +struct s1 {
> +    unsigned char _4;
> +    long _1;
> +};
> +struct s2 {
> +    union {
> +        struct s3 {
> +            unsigned char _1;
> +            struct s4 _0;
> +        } var_0;
> +        struct s1 var_1;
> +    } DATA;
> +};
> +int f1(int arg0) { return arg0 > 12345; }
> +__attribute__((noinline))
> +struct s4 f2(int arg0) {
> +    struct s4 rv = {arg0};
> +    return rv;
> +}
> +struct s2 f3(int arg0) {
> +    struct s2 rv;
> +    struct s1 var6 = {0};
> +    struct s4 var7;
> +    if (f1(arg0)) {
> +        rv.DATA.var_1 = var6;
> +        return rv;
> +    } else {
> +        rv.DATA.var_0._1 = 2;
> +        var7 = f2(arg0);
> +        rv.DATA.var_0._0 = var7;
> +        return rv;
> +    }
> +}
> +int main() {
> +  if (f3(12345).DATA.var_0._0._0 == 12345)
> +    ;
> +  else
> +    __builtin_abort();
> +  if (f3(12344).DATA.var_0._0._0 == 12344)
> +    ;
> +  else
> +    __builtin_abort();
> +}
> diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc
> index 23236fc6537..240af676ea3 100644
> --- a/gcc/tree-sra.cc
> +++ b/gcc/tree-sra.cc
> @@ -2889,7 +2889,10 @@ analyze_access_subtree (struct access *root, struct 
> access *parent,
>  
>    for (child = root->first_child; child; child = child->next_sibling)
>      {
> -      hole |= covered_to < child->offset;
> +      if (totally)
> +     covered_to = child->offset;
> +      else
> +     hole |= covered_to < child->offset;
>        sth_created |= analyze_access_subtree (child, root,
>                                            allow_replacements && !scalar
>                                            && !root->grp_partial_lhs,
> @@ -2900,6 +2903,8 @@ analyze_access_subtree (struct access *root, struct 
> access *parent,
>       covered_to += child->size;
>        else
>       hole = true;
> +      if (totally && !hole)
> +     covered_to = limit;
>      }
>  
>    if (allow_replacements && scalar && !root->first_child
> @@ -2972,7 +2977,7 @@ analyze_access_subtree (struct access *root, struct 
> access *parent,
>       root->grp_total_scalarization = 0;
>      }
>  
> -  if (!hole || totally)
> +  if (!hole)
>      root->grp_covered = 1;
>    else if (root->grp_write || comes_initialized_p (root->base))
>      root->grp_unscalarized_data = 1; /* not covered and written to */
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to