The gc compiler recognizes append(s, make(T, n)...), and generates code to directly zero the tail instead of allocating a new slice and copying. This CL lets the Go frontend do basically the same.
The difficulty is that at the point we handle append, there may already be temporaries introduced (e.g. in order_evaluations), which makes it hard to find the append-of-make pattern. The compiler could "see through" the value of a temporary, but it is only safe to do if the temporary is not assigned multiple times. For this, we add tracking of assignments and uses for temporaries.
This also helps in optimizing non-escape slice make. We already optimize non-escape slice make with constant len/cap to stack allocation. But it failed to handle things like f(make(T, n)) (where the slice doesn't escape and n is constant), because of the temporary. With tracking of temporary assignments and uses, it can handle this now as well.
38ba9eec651 compiler: optimize append of make
gcc/go/gofrontend/MERGE | 2 +-
gcc/go/gofrontend/expressions.cc | 236 +++++++++++++++++++++++++++++++--------
gcc/go/gofrontend/expressions.h | 5 +
gcc/go/gofrontend/gogo.h | 17 +--
gcc/go/gofrontend/statements.cc | 3 +
gcc/go/gofrontend/statements.h | 37 +++++-
gcc/go/gofrontend/wb.cc | 35 +-----
libgo/runtime/go-runtime-error.c | 24 ++--
8 files changed, 266 insertions(+), 93 deletions(-)