cmd/internal/gc: inline x := y.(*T) and x, ok := y.(*T)

These can be implemented with just a compare and a move instruction.
Do so, avoiding the overhead of a call into the runtime.

These assertions are a significant cost in Go code that uses interface{}
as a safe alternative to C's void* (or unsafe.Pointer), such as the
current version of the Go compiler.

*T here includes pointer to T but also any Go type represented as
a single pointer (chan, func, map). It does not include [1]*T or struct{*int}.
That requires more work in other parts of the compiler; there is a TODO.

Change-Id: I7ff681c20d2c3eb6ad11dd7b3a37b1f3dda23965
Reviewed-on: https://go-review.googlesource.com/7862
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/src/cmd/internal/gc/cgen.go b/src/cmd/internal/gc/cgen.go
index 610f251..7566dda 100644
--- a/src/cmd/internal/gc/cgen.go
+++ b/src/cmd/internal/gc/cgen.go
@@ -54,6 +54,10 @@
 			Cgen_eface(n, res)
 		}
 		return
+
+	case ODOTTYPE:
+		cgen_dottype(n, res, nil)
+		return
 	}
 
 	if n.Ullman >= UINF {
@@ -1224,12 +1228,19 @@
 				Agenr(nl, &n3, res)
 			} else {
 				if nl.Addable == 0 {
+					if res != nil && res.Op == OREGISTER { // give up res, which we don't need yet.
+						Regfree(res)
+					}
+
 					// igen will need an addressable node.
 					var tmp2 Node
 					Tempname(&tmp2, nl.Type)
-
 					Cgen(nl, &tmp2)
 					nl = &tmp2
+
+					if res != nil && res.Op == OREGISTER { // reacquire res
+						Regrealloc(res)
+					}
 				}
 
 				Igen(nl, &nlen, res)
@@ -1448,16 +1459,10 @@
 		cgen_call(n, 0)
 		cgen_aret(n, res)
 
-	case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
+	case OEFACE, ODOTTYPE, OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
 		var n1 Node
 		Tempname(&n1, n.Type)
-		Cgen_slice(n, &n1)
-		Agen(&n1, res)
-
-	case OEFACE:
-		var n1 Node
-		Tempname(&n1, n.Type)
-		Cgen_eface(n, &n1)
+		Cgen(n, &n1)
 		Agen(&n1, res)
 
 	case OINDEX:
@@ -1520,15 +1525,12 @@
 	Regfree(&n2)
 }
 
-/*
- * generate:
- *	newreg = &n;
- *	res = newreg
- *
- * on exit, a has been changed to be *newreg.
- * caller must Regfree(a).
- * The generated code checks that the result is not *nil.
- */
+// Igen computes the address &n, stores it in a register r,
+// and rewrites a to refer to *r. The chosen r may be the
+// stack pointer, it may be borrowed from res, or it may
+// be a newly allocated register. The caller must call Regfree(a)
+// to free r when the address is no longer needed.
+// The generated code ensures that &n is not nil.
 func Igen(n *Node, a *Node, res *Node) {
 	if Debug['g'] != 0 {
 		Dump("\nigen-n", n)