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.