go/ssa: opt: avoid an allocation

In the dom tree traversal, the final child of each node now
inherits the parent's renaming map, reducing garbage.

This reduces allocations by 1.4% and bytes allocated by 2.0% when
building SSA for the entire standard library.

Change-Id: Id19b6d6766b3e0bf32d1db1238eff8a42d11b242
Reviewed-on: https://go-review.googlesource.com/45833
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/go/ssa/lift.go b/go/ssa/lift.go
index 091992f..00c8a72 100644
--- a/go/ssa/lift.go
+++ b/go/ssa/lift.go
@@ -630,10 +630,15 @@
 
 	// Continue depth-first recursion over domtree, pushing a
 	// fresh copy of the renaming map for each subtree.
-	for _, v := range u.dom.children {
-		// TODO(adonovan): opt: avoid copy on final iteration; use destructive update.
-		r := make([]Value, len(renaming))
-		copy(r, renaming)
+	for i, v := range u.dom.children {
+		r := renaming
+		if i < len(u.dom.children)-1 {
+			// On all but the final iteration, we must make
+			// a copy to avoid destructive update.
+			r = make([]Value, len(renaming))
+			copy(r, renaming)
+		}
 		rename(v, r, newPhis)
 	}
+
 }