gc: inline append when len<cap

issue 1604

R=rsc, bradfitz
CC=golang-dev
https://golang.org/cl/4313062
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 920725c..2231525 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -915,7 +915,7 @@
 	Node nodes[5];
 	Node n1, n2, nres, ntemp;
 	vlong v;
-	int i, narg;
+	int i, narg, nochk;
 
 	if(n->op != OCALLFUNC)
 		goto no;
@@ -953,6 +953,7 @@
 	// len = hb[3] - lb[2] (destroys hb)
 	n2 = *res;
 	n2.xoffset += Array_nel;
+	n2.type = types[TUINT32];
 
 	if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) {
 		v = mpgetfix(nodes[3].val.u.xval) -
@@ -971,6 +972,7 @@
 	// cap = nel[1] - lb[2] (destroys nel)
 	n2 = *res;
 	n2.xoffset += Array_cap;
+	n2.type = types[TUINT32];
 
 	if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) {
 		v = mpgetfix(nodes[1].val.u.xval) -
@@ -999,6 +1001,7 @@
 	// ary = old[0] + (lb[2] * width[4]) (destroys old)
 	n2 = *res;
 	n2.xoffset += Array_array;
+	n2.type = types[tptr];
 
 	if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) {
 		v = mpgetfix(nodes[2].val.u.xval) *
@@ -1026,6 +1029,7 @@
 sliceslice:
 	if(!fix64(n->list, narg))
 		goto no;
+	nochk = n->etype;  // skip bounds checking
 	ntemp.op = OXXX;
 	if(!sleasy(n->list->n->right)) {
 		Node *n0;
@@ -1055,11 +1059,13 @@
 		n2 = nodes[0];
 		n2.xoffset += Array_nel;
 		n2.type = types[TUINT32];
-		cmpandthrow(&nodes[1], &n2);
+		if(!nochk)
+			cmpandthrow(&nodes[1], &n2);
 
 		// ret.nel = old.nel[0]-lb[1];
 		n2 = nodes[0];
 		n2.xoffset += Array_nel;
+		n2.type = types[TUINT32];
 	
 		regalloc(&n1, types[TUINT32], N);
 		gins(optoas(OAS, types[TUINT32]), &n2, &n1);
@@ -1068,22 +1074,25 @@
 	
 		n2 = nres;
 		n2.xoffset += Array_nel;
+		n2.type = types[TUINT32];
 		gins(optoas(OAS, types[TUINT32]), &n1, &n2);
 		regfree(&n1);
 	} else {	// old[lb:hb]
-		// if(hb[2] > old.cap[0]) goto throw;
 		n2 = nodes[0];
 		n2.xoffset += Array_cap;
 		n2.type = types[TUINT32];
-		cmpandthrow(&nodes[2], &n2);
-
-		// if(lb[1] > hb[2]) goto throw;
-		cmpandthrow(&nodes[1], &nodes[2]);
+		if (!nochk) {
+			// if(hb[2] > old.cap[0]) goto throw;
+			cmpandthrow(&nodes[2], &n2);
+			// if(lb[1] > hb[2]) goto throw;
+			cmpandthrow(&nodes[1], &nodes[2]);
+		}
 
 		// ret.len = hb[2]-lb[1]; (destroys hb[2])
 		n2 = nres;
 		n2.xoffset += Array_nel;
-	
+		n2.type = types[TUINT32];
+
 		if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) {
 			v = mpgetfix(nodes[2].val.u.xval) -
 				mpgetfix(nodes[1].val.u.xval);
@@ -1102,6 +1111,7 @@
 	// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
 	n2 = nodes[0];
 	n2.xoffset += Array_cap;
+	n2.type = types[TUINT32];
 
 	regalloc(&n1, types[TUINT32], &nodes[2]);
 	gins(optoas(OAS, types[TUINT32]), &n2, &n1);
@@ -1110,12 +1120,14 @@
 
 	n2 = nres;
 	n2.xoffset += Array_cap;
+	n2.type = types[TUINT32];
 	gins(optoas(OAS, types[TUINT32]), &n1, &n2);
 	regfree(&n1);
 
 	// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
 	n2 = nodes[0];
 	n2.xoffset += Array_array;
+	n2.type = types[tptr];
 
 	regalloc(&n1, types[tptr], &nodes[1]);
 	if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) {
@@ -1135,6 +1147,7 @@
 
 	n2 = nres;
 	n2.xoffset += Array_array;
+	n2.type = types[tptr];
 	gins(optoas(OAS, types[tptr]), &n1, &n2);
 	regfree(&n1);