On Tue, 10 Dec 2024, Jan Hubicka wrote: > Hi, > int: > struct foo > { > int a; > void bar() const; > ~foo() > { > if (a != 42) > __builtin_abort (); > } > }; > __attribute__ ((noinline)) > void test(const struct foo a) > { > int b = a.a; > a.bar(); > if (a.a != b) > __builtin_printf ("optimize me away"); > } > struct foo is passed by invisible reference. As discussed in the PR, > since it is declared const, it can not change before function test > returns. This makes it possible to optimize out the conditional.
Doesn't this break the case where 'a' is declared mutable? Richard. > We already support this for fnspec "r" attribute. This patch simply adds > same logic for const parameters passed by invisible reference. > To simplify the implementation I also extended attr-fnspec to allow > NULL in the constructor, so we can use same loop no matter when fnspec > is present. > > Bootstrapped/regtested x86_64-linux, OK? > > gcc/ChangeLog: > > PR tree-optimization/103827 > * attr-fnspec.h (attr_fnspec constructor): Allow NULL_TREE. > * tree-into-ssa.cc (pass_build_ssa::execute): Also set > SSA_NAME_POINTS_TO_READONLY_MEMORY for parameters passed by > invisible reference and declared const. > > gcc/testsuite/ChangeLog: > > * g++.dg/tree-ssa/pr103827.C: New test. > > > diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h > index aef4701e6d1..76053d88b09 100644 > --- a/gcc/attr-fnspec.h > +++ b/gcc/attr-fnspec.h > @@ -93,8 +97,8 @@ public: > verify (); > } > attr_fnspec (const_tree identifier) > - : str (TREE_STRING_POINTER (identifier)), > - len (TREE_STRING_LENGTH (identifier)) > + : str (identifier ? TREE_STRING_POINTER (identifier) : NULL), > + len (identifier ? TREE_STRING_LENGTH (identifier) : 0) > { > if (flag_checking) > verify (); > diff --git a/gcc/tree-into-ssa.cc b/gcc/tree-into-ssa.cc > index df1fb186962..0267a86f1cc 100644 > --- a/gcc/tree-into-ssa.cc > +++ b/gcc/tree-into-ssa.cc > @@ -2555,25 +2556,23 @@ pass_build_ssa::execute (function *fun) > SET_SSA_NAME_VAR_OR_IDENTIFIER (name, DECL_NAME (decl)); > } > > - /* Initialize SSA_NAME_POINTS_TO_READONLY_MEMORY. */ > + /* Initialize SSA_NAME_POINTS_TO_READONLY_MEMORY using fnspec or for > + values passed by invisible reference declared const. */ > tree fnspec_tree > = lookup_attribute ("fn spec", > TYPE_ATTRIBUTES (TREE_TYPE (fun->decl))); > - if (fnspec_tree) > - { > - attr_fnspec fnspec (TREE_VALUE (TREE_VALUE (fnspec_tree))); > - unsigned i = 0; > - for (tree arg = DECL_ARGUMENTS (cfun->decl); > - arg; arg = DECL_CHAIN (arg), ++i) > + attr_fnspec fnspec (fnspec_tree ? TREE_VALUE (TREE_VALUE (fnspec_tree)) : > NULL); > + i = 0; > + for (tree arg = DECL_ARGUMENTS (cfun->decl); > + arg; arg = DECL_CHAIN (arg), ++i) > + { > + if ((fnspec.arg_specified_p (i) && fnspec.arg_readonly_p (i)) > + || (DECL_BY_REFERENCE (arg) > + && TYPE_READONLY (TREE_TYPE (TREE_TYPE (arg))))) > { > - if (!fnspec.arg_specified_p (i)) > - break; > - if (fnspec.arg_readonly_p (i)) > - { > - tree name = ssa_default_def (fun, arg); > - if (name) > - SSA_NAME_POINTS_TO_READONLY_MEMORY (name) = 1; > - } > + tree name = ssa_default_def (fun, arg); > + if (name) > + SSA_NAME_POINTS_TO_READONLY_MEMORY (name) = 1; > } > } > diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr103827.C > b/gcc/testsuite/g++.dg/tree-ssa/pr103827.C > new file mode 100644 > index 00000000000..6059fe514b1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/tree-ssa/pr103827.C > @@ -0,0 +1,22 @@ > +// { dg-do compile } > +// { dg-options "-O1 -fdump-tree-optimized" } > +struct foo > +{ > + int a; > + void bar() const; > + ~foo() > + { > + if (a != 42) > + __builtin_abort (); > + } > +}; > +__attribute__ ((noinline)) > +void test(const struct foo a) > +{ > + int b = a.a; > + a.bar(); > + if (a.a != b) > + __builtin_printf ("optimize me away"); > +} > + > +/* { dg-final { scan-tree-dump-not "optimize me away" "optimized" } } */ > -- 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)