public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-7668] c++: fold calls to std::move/forward [PR96780]
@ 2022-03-16 12:26 Patrick Palka
  0 siblings, 0 replies; only message in thread
From: Patrick Palka @ 2022-03-16 12:26 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:e55c5e24b97ad8ddc44588da18e894c139e02c0a

commit r12-7668-ge55c5e24b97ad8ddc44588da18e894c139e02c0a
Author: Patrick Palka <ppalka@redhat.com>
Date:   Wed Mar 16 08:25:54 2022 -0400

    c++: fold calls to std::move/forward [PR96780]
    
    A well-formed call to std::move/forward is equivalent to a cast, but the
    former being a function call means the compiler generates debug info,
    which persists even after the call gets inlined, for an operation that's
    never interesting to debug.
    
    This patch addresses this problem by folding calls to std::move/forward
    and other cast-like functions into simple casts as part of the frontend's
    general expression folding routine.  This behavior is controlled by a
    new flag -ffold-simple-inlines, and otherwise by -fno-inline, so that
    users can enable this folding with -O0 (which implies -fno-inline).
    
    After this patch with -O2 and a non-checking compiler, debug info size
    for some testcases from range-v3 and cmcstl2 decreases by as much as ~10%
    and overall compile time and memory usage decreases by ~2%.
    
            PR c++/96780
    
    gcc/ChangeLog:
    
            * doc/invoke.texi (C++ Dialect Options): Document
            -ffold-simple-inlines.
    
    gcc/c-family/ChangeLog:
    
            * c.opt: Add -ffold-simple-inlines.
    
    gcc/cp/ChangeLog:
    
            * cp-gimplify.cc (cp_fold) <case CALL_EXPR>: Fold calls to
            std::move/forward and other cast-like functions into simple
            casts.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/opt/pr96780.C: New test.

Diff:
---
 gcc/c-family/c.opt                 |  4 ++++
 gcc/cp/cp-gimplify.cc              | 38 +++++++++++++++++++++++++++++++++++++-
 gcc/doc/invoke.texi                | 10 ++++++++++
 gcc/testsuite/g++.dg/opt/pr96780.C | 38 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 9cfd2a6bc4e..9a4828ebe37 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1731,6 +1731,10 @@ Support dynamic initialization of thread-local variables in a different translat
 fexternal-templates
 C++ ObjC++ WarnRemoved
 
+ffold-simple-inlines
+C++ ObjC++ Optimization Var(flag_fold_simple_inlines)
+Fold calls to simple inline functions.
+
 ffor-scope
 C++ ObjC++ WarnRemoved
 
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index d7323fb5c09..e4c2644af15 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "file-prefix-map.h"
 #include "cgraph.h"
 #include "omp-general.h"
+#include "opts.h"
 
 /* Forward declarations.  */
 
@@ -2756,9 +2757,44 @@ cp_fold (tree x)
 
     case CALL_EXPR:
       {
-	int sv = optimize, nw = sv;
 	tree callee = get_callee_fndecl (x);
 
+	/* "Inline" calls to std::move/forward and other cast-like functions
+	   by simply folding them into a corresponding cast to their return
+	   type.  This is cheaper than relying on the middle end to do so, and
+	   also means we avoid generating useless debug info for them at all.
+
+	   At this point the argument has already been converted into a
+	   reference, so it suffices to use a NOP_EXPR to express the
+	   cast.  */
+	if ((OPTION_SET_P (flag_fold_simple_inlines)
+	     ? flag_fold_simple_inlines
+	     : !flag_no_inline)
+	    && call_expr_nargs (x) == 1
+	    && decl_in_std_namespace_p (callee)
+	    && DECL_NAME (callee) != NULL_TREE
+	    && (id_equal (DECL_NAME (callee), "move")
+		|| id_equal (DECL_NAME (callee), "forward")
+		|| id_equal (DECL_NAME (callee), "addressof")
+		/* This addressof equivalent is used heavily in libstdc++.  */
+		|| id_equal (DECL_NAME (callee), "__addressof")
+		|| id_equal (DECL_NAME (callee), "as_const")))
+	  {
+	    r = CALL_EXPR_ARG (x, 0);
+	    /* Check that the return and argument types are sane before
+	       folding.  */
+	    if (INDIRECT_TYPE_P (TREE_TYPE (x))
+		&& INDIRECT_TYPE_P (TREE_TYPE (r)))
+	      {
+		if (!same_type_p (TREE_TYPE (x), TREE_TYPE (r)))
+		  r = build_nop (TREE_TYPE (x), r);
+		x = cp_fold (r);
+		break;
+	      }
+	  }
+
+	int sv = optimize, nw = sv;
+
 	/* Some built-in function calls will be evaluated at compile-time in
 	   fold ().  Set optimize to 1 when folding __builtin_constant_p inside
 	   a constexpr function so that fold_builtin_1 doesn't fold it to 0.  */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 2a14e1a9472..d65979bba3f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3124,6 +3124,16 @@ On targets that support symbol aliases, the default is
 @option{-fextern-tls-init}.  On targets that do not support symbol
 aliases, the default is @option{-fno-extern-tls-init}.
 
+@item -ffold-simple-inlines
+@itemx -fno-fold-simple-inlines
+@opindex ffold-simple-inlines
+@opindex fno-fold-simple-inlines
+Permit the C++ frontend to fold calls to @code{std::move}, @code{std::forward},
+@code{std::addressof} and @code{std::as_const}.  In contrast to inlining, this
+means no debug information will be generated for such calls.  Since these
+functions are rarely interesting to debug, this flag is enabled by default
+unless @option{-fno-inline} is active.
+
 @item -fno-gnu-keywords
 @opindex fno-gnu-keywords
 @opindex fgnu-keywords
diff --git a/gcc/testsuite/g++.dg/opt/pr96780.C b/gcc/testsuite/g++.dg/opt/pr96780.C
new file mode 100644
index 00000000000..61e11855eeb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr96780.C
@@ -0,0 +1,38 @@
+// PR c++/96780
+// Verify calls to std::move/forward are folded away by the frontend.
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-ffold-simple-inlines -fdump-tree-gimple" }
+
+#include <utility>
+
+struct A;
+
+extern A& a;
+extern const A& ca;
+
+void f() {
+  auto&& x1 = std::move(a);
+  auto&& x2 = std::forward<A>(a);
+  auto&& x3 = std::forward<A&>(a);
+
+  auto&& x4 = std::move(ca);
+  auto&& x5 = std::forward<const A>(ca);
+  auto&& x6 = std::forward<const A&>(ca);
+
+  auto x7 = std::addressof(a);
+  auto x8 = std::addressof(ca);
+#if __GLIBCXX__
+  auto x9 = std::__addressof(a);
+  auto x10 = std::__addressof(ca);
+#endif
+#if __cpp_lib_as_const
+  auto&& x11 = std::as_const(a);
+  auto&& x12 = std::as_const(ca);
+#endif
+}
+
+// { dg-final { scan-tree-dump-not "= std::move" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::forward" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::addressof" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::__addressof" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::as_const" "gimple" } }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-03-16 12:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-16 12:26 [gcc r12-7668] c++: fold calls to std::move/forward [PR96780] Patrick Palka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).