cmd/internal/gc, cmd/7g: use zero register in Componentgen

Fixes #9855

Use an architectural zero register as the source for zeroing, if available.

Change-Id: Ie5b4ba4e3d356c6f892bfd1cebd14d5152bdeeb0
Reviewed-on: https://go-review.googlesource.com/8722
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/src/cmd/7g/galign.go b/src/cmd/7g/galign.go
index c21cb67..3ad786a 100644
--- a/src/cmd/7g/galign.go
+++ b/src/cmd/7g/galign.go
@@ -49,6 +49,7 @@
 	gc.Thearch.REGRETURN = arm64.REG_R0
 	gc.Thearch.REGMIN = arm64.REG_R0
 	gc.Thearch.REGMAX = arm64.REG_R31
+	gc.Thearch.REGZERO = arm64.REGZERO
 	gc.Thearch.FREGMIN = arm64.REG_F0
 	gc.Thearch.FREGMAX = arm64.REG_F31
 	gc.Thearch.MAXWIDTH = MAXWIDTH
diff --git a/src/cmd/internal/gc/gen.go b/src/cmd/internal/gc/gen.go
index fde0a19..e95ddeb 100644
--- a/src/cmd/internal/gc/gen.go
+++ b/src/cmd/internal/gc/gen.go
@@ -1183,12 +1183,18 @@
 		}
 	} else {
 		// When zeroing, prepare a register containing zero.
-		var tmp Node
-		Nodconst(&tmp, nl.Type, 0)
+		if Thearch.REGZERO != 0 {
+			// cpu has a dedicated zero register
+			Nodreg(&nodr, Types[TUINT], Thearch.REGZERO)
+		} else {
+			// no dedicated zero register
+			var tmp Node
+			Nodconst(&tmp, nl.Type, 0)
 
-		Regalloc(&nodr, Types[TUINT], nil)
-		Thearch.Gmove(&tmp, &nodr)
-		defer Regfree(&nodr)
+			Regalloc(&nodr, Types[TUINT], nil)
+			Thearch.Gmove(&tmp, &nodr)
+			defer Regfree(&nodr)
+		}
 	}
 
 	// nl and nr are 'cadable' which basically means they are names (variables) now.
diff --git a/src/cmd/internal/gc/go.go b/src/cmd/internal/gc/go.go
index 5803f39..25ada55 100644
--- a/src/cmd/internal/gc/go.go
+++ b/src/cmd/internal/gc/go.go
@@ -769,6 +769,7 @@
 	REGRETURN    int // AX
 	REGMIN       int
 	REGMAX       int
+	REGZERO      int // architectural zero register, if available
 	FREGMIN      int
 	FREGMAX      int
 	MAXWIDTH     int64