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.
This commit is contained in:
Patrick Palka 2022-03-16 08:25:54 -04:00
parent 818e305ea6
commit e55c5e24b9
4 changed files with 89 additions and 1 deletions

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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" } }