cmd/internal/gc: clean up Componentgen

Update #9855

In preparation for introducing direct use of a zero register on
platforms that support it, take the opportunity to clean up
Componentgen a bit.

Change-Id: I120ce1ffcca8c4f7603bfe76bfa1aedd27ebb4d2
Reviewed-on: https://go-review.googlesource.com/8691
Run-TryBot: Dave Cheney <dave@cheney.net>
Reviewed-by: Minux Ma <minux@golang.org>
diff --git a/src/cmd/internal/gc/gen.go b/src/cmd/internal/gc/gen.go
index 4b7344a..fde0a19 100644
--- a/src/cmd/internal/gc/gen.go
+++ b/src/cmd/internal/gc/gen.go
@@ -1116,26 +1116,16 @@
 	}
 }
 
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
+// Componentgen copies a composite value by moving its individual components.
+// Slices, strings and interfaces are supported. Small structs or arrays with
+// elements of basic type are also supported.
+// nr is nil when assigning a zero value.
 func Componentgen(nr *Node, nl *Node) bool {
-	var nodl Node
-	var nodr Node
-
-	freel := 0
-	freer := 0
-
-	var isConstString bool
+	var nodl, nodr Node
 
 	switch nl.Type.Etype {
 	default:
-		goto no
+		return false
 
 	case TARRAY:
 		t := nl.Type
@@ -1150,16 +1140,16 @@
 			break
 		}
 
-		goto no
+		return false
 
-		// Small structs with non-fat types are ok.
-	// Zero-sized structs are treated separately elsewhere.
 	case TSTRUCT:
+		// Small structs with non-fat types are ok.
+		// Zero-sized structs are treated separately elsewhere.
 		fldcount := int64(0)
 
 		for t := nl.Type.Type; t != nil; t = t.Down {
 			if Isfat(t.Type) && !Isslice(t) {
-				goto no
+				return false
 			}
 			if t.Etype != TFIELD {
 				Fatal("componentgen: not a TFIELD: %v", Tconv(t, obj.FmtLong))
@@ -1168,28 +1158,28 @@
 		}
 
 		if fldcount == 0 || fldcount > 4 {
-			goto no
+			return false
 		}
 
 	case TSTRING, TINTER:
 		break
 	}
 
-	isConstString = Isconst(nr, CTSTR)
+	isConstString := Isconst(nr, CTSTR)
 	nodl = *nl
 	if !cadable(nl) {
 		if nr != nil && !cadable(nr) && !isConstString {
-			goto no
+			return false
 		}
 		Igen(nl, &nodl, nil)
-		freel = 1
+		defer Regfree(&nodl)
 	}
 
 	if nr != nil {
 		nodr = *nr
 		if !cadable(nr) && !isConstString {
 			Igen(nr, &nodr, nil)
-			freer = 1
+			defer Regfree(&nodr)
 		}
 	} else {
 		// When zeroing, prepare a register containing zero.
@@ -1198,7 +1188,7 @@
 
 		Regalloc(&nodr, Types[TUINT], nil)
 		Thearch.Gmove(&tmp, &nodr)
-		freer = 1
+		defer Regfree(&nodr)
 	}
 
 	// nl and nr are 'cadable' which basically means they are names (variables) now.
@@ -1206,12 +1196,15 @@
 	// VARDEF we generate will mark the old value as dead incorrectly.
 	// (And also the assignments are useless.)
 	if nr != nil && nl.Op == ONAME && nr.Op == ONAME && nl == nr {
-		goto yes
+		return true
 	}
 
 	switch nl.Type.Etype {
-	// componentgen for arrays.
+	default:
+		return false
+
 	case TARRAY:
+		// componentgen for arrays.
 		if nl.Op == ONAME {
 			Gvardef(nl)
 		}
@@ -1228,8 +1221,7 @@
 				nodl.Xoffset += t.Type.Width
 				nodr.Xoffset += t.Type.Width
 			}
-
-			goto yes
+			return true
 		}
 
 		// componentgen for slices.
@@ -1263,8 +1255,7 @@
 		}
 
 		Thearch.Gmove(&nodr, &nodl)
-
-		goto yes
+		return true
 
 	case TSTRING:
 		if nl.Op == ONAME {
@@ -1297,8 +1288,7 @@
 		}
 
 		Thearch.Gmove(&nodr, &nodl)
-
-		goto yes
+		return true
 
 	case TINTER:
 		if nl.Op == ONAME {
@@ -1323,8 +1313,7 @@
 		}
 
 		Thearch.Gmove(&nodr, &nodl)
-
-		goto yes
+		return true
 
 	case TSTRUCT:
 		if nl.Op == ONAME {
@@ -1353,27 +1342,8 @@
 				Thearch.Gmove(&nodr, &nodl)
 			}
 		}
-
-		goto yes
+		return true
 	}
-
-no:
-	if freer != 0 {
-		Regfree(&nodr)
-	}
-	if freel != 0 {
-		Regfree(&nodl)
-	}
-	return false
-
-yes:
-	if freer != 0 {
-		Regfree(&nodr)
-	}
-	if freel != 0 {
-		Regfree(&nodl)
-	}
-	return true
 }
 
 func cadable(n *Node) bool {