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.

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" } } */

Reply via email to