https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119387
Patrick Palka <ppalka at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jason at gcc dot gnu.org
--- Comment #16 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Stepping through the constexpr evaluation of the reduced comment #14 testcase,
I noticed a lot of unnecessary casts when passing a reference argument to a
reference parameter of the same type, e.g. for
void f(int&);
void g(int& x) { f(x); }
we represent the call as
f ((int &) (int *) x);
(at least until it goes through cp_fold which gets rid of the unnecessary casts
but sometimes we may attempt constexpr folding before cp_fold).
Constexpr evaluation of these unnecessary casts seems to create a ton of
garbage. Avoiding creating these unnecessary casts in the first place with
e.g.
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c1c8987ec8b..ff84d6591fa 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9280,6 +9280,9 @@ convert_like_internal (conversion *convs, tree expr, tree
fn, int argnum,
expr = build_target_expr_with_type (expr, type, complain);
}
+ if (REFERENCE_REF_P (expr))
+ return cp_convert (ref_type, TREE_OPERAND (expr, 0), complain);
+
/* Take the address of the thing to which we will bind the
reference. */
expr = cp_build_addr_expr (expr, complain);
helps a lot memory-wise. For the original testcase (with -g), memory use drops
from ~7GB to ~4GB and compile time from ~6m to ~2m! For the reduced testcase,
memory use drops 300MB to 80MB.
Unfortunately the above patch causes FAILs in g++.dg/init/elide6.C and some
-Wredundant-move tests, which I haven't looked into closely but I think they
can be resolved.