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 <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)