gc: better compilation of floating point +=

R=ken2
CC=golang-dev
https://golang.org/cl/255042
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 3f32e60..758e140 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -479,27 +479,35 @@
 	}
 
 hard:
-	if(nr->ullman > nl->ullman) {
+	n2.op = 0;
+	n1.op = 0;
+	if(nr->ullman >= nl->ullman || nl->addable) {
 		regalloc(&n2, nr->type, N);
 		cgen(nr, &n2);
-		igen(nl, &n1, N);
+		nr = &n2;
 	} else {
-		igen(nl, &n1, N);
-		regalloc(&n2, nr->type, N);
+		tempname(&n2, nr->type);
 		cgen(nr, &n2);
+		nr = &n2;
+	}
+	if(!nl->addable) {
+		igen(nl, &n1, N);
+		nl = &n1;
 	}
 
 	n3 = *n;
-	n3.left = &n1;
-	n3.right = &n2;
+	n3.left = nl;
+	n3.right = nr;
 	n3.op = n->etype;
 
 	regalloc(&n4, nl->type, N);
 	cgen(&n3, &n4);
-	gmove(&n4, &n1);
+	gmove(&n4, nl);
 
-	regfree(&n1);
-	regfree(&n2);
+	if(n1.op)
+		regfree(&n1);
+	if(n2.op == OREGISTER)
+		regfree(&n2);
 	regfree(&n4);
 	goto ret;
 
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index 731e922..45fd17b 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -432,27 +432,35 @@
 	}
 
 hard:
-	if(nr->ullman > nl->ullman) {
+	n2.op = 0;
+	n1.op = 0;
+	if(nr->ullman >= nl->ullman || nl->addable) {
 		regalloc(&n2, nr->type, N);
 		cgen(nr, &n2);
-		igen(nl, &n1, N);
+		nr = &n2;
 	} else {
-		igen(nl, &n1, N);
-		regalloc(&n2, nr->type, N);
+		tempname(&n2, nr->type);
 		cgen(nr, &n2);
+		nr = &n2;
+	}
+	if(!nl->addable) {
+		igen(nl, &n1, N);
+		nl = &n1;
 	}
 
 	n3 = *n;
-	n3.left = &n1;
-	n3.right = &n2;
+	n3.left = nl;
+	n3.right = nr;
 	n3.op = n->etype;
 
 	regalloc(&n4, nl->type, N);
 	cgen(&n3, &n4);
-	gmove(&n4, &n1);
+	gmove(&n4, nl);
 
-	regfree(&n1);
-	regfree(&n2);
+	if(n1.op)
+		regfree(&n1);
+	if(n2.op == OREGISTER)
+		regfree(&n2);
 	regfree(&n4);
 
 ret:
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 1185ee4..5adf29a 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -18,7 +18,7 @@
 			reg[n->val.u.reg]++;
 		return;
 	}
-	if(n->type->width > widthptr)
+	if(n->type->width > widthptr && !isfloat[n->type->etype])
 		tempname(n1, n->type);
 	else
 		regalloc(n1, n->type, rg);
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 549488d1..f6fa7da 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -471,21 +471,34 @@
 	}
 
 hard:
-	tempname(&n2, nr->type);
-	cgen(nr, &n2);
-
-	igen(nl, &n1, N);
+	n2.op = 0;
+	n1.op = 0;
+	if(nr->ullman >= nl->ullman || nl->addable) {
+		mgen(nr, &n2, N);
+		nr = &n2;
+		nr = &n2;
+	} else {
+		tempname(&n2, nr->type);
+		cgen(nr, &n2);
+		nr = &n2;
+	}
+	if(!nl->addable) {
+		igen(nl, &n1, N);
+		nl = &n1;
+	}
 
 	n3 = *n;
-	n3.left = &n1;
-	n3.right = &n2;
+	n3.left = nl;
+	n3.right = nr;
 	n3.op = n->etype;
 
-	tempname(&n4, nl->type);
-	cgen(&n3, &n4);
-	gmove(&n4, &n1);
+	mgen(&n3, &n4, N);
+	gmove(&n4, nl);
 
-	regfree(&n1);
+	if(n1.op)
+		regfree(&n1);
+	mfree(&n2);
+	mfree(&n4);
 
 ret:
 	;
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 2f15130..5ee82ee 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -823,10 +823,13 @@
 		}
 
 		/*
-		 * on 32-bit arch, rewrite 64-bit ops into l = l op r
+		 * on 32-bit arch, rewrite 64-bit ops into l = l op r.
+		 * on 386, rewrite float ops into l = l op r.
+		 * TODO(rsc): Maybe this rewrite should be done always?
 		 */
 		et = n->left->type->etype;
-		if(widthptr == 4 && (et == TUINT64 || et == TINT64)) {
+		if((widthptr == 4 && (et == TUINT64 || et == TINT64)) ||
+		   (thechar == '8' && isfloat[et])) {
 			l = safeexpr(n->left, init);
 			r = nod(OAS, l, nod(n->etype, l, n->right));
 			typecheck(&r, Etop);