code: plan9front

Download patch

ref: bc8eb6ef45d6831975606eb9932c6e72dd470b82
parent: 693325b47ace28d68459911ac3d670bb0c0db79b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Feb 4 15:54:45 EST 2023

7c: help and improve peephole optimizer

When using non signed integer variables, the registerizer
would produce multiple converting load instructions on each
use, which gives the peephole optimizer a hard time as it
assumes that converting move instructions are there to
actually change the data type (hence it cannot eleminate
them).

To avoid this, when we replace a variable reference with
a register, we check that the move instruction is in fact
the same as used in the initial load (which is based
on variable type only), and replace the instruction with
a full register move (AMOV).

The peephole optimizer then is able to eleminate these
instruction giving way better code.

--- a/sys/src/cmd/7c/peep.c
+++ b/sys/src/cmd/7c/peep.c
@@ -57,8 +57,9 @@
 				excise(r);
 				t++;
 			}
-		}
-		if(p->as == ASXTW){
+		} else
+		if(p->as == ASXTW
+		&& regtyp(&p->from) && regtyp(&p->to)){
 			r1 = findpre(r, &p->from);
 			if(r1 != R){
 				p1 = r1->prog;
@@ -68,11 +69,22 @@
 				case AMOVH:
 				case AMOVHU:
 				case AMOVW:
-					p->as = AMOVW;
+					if(p1->to.type == p->from.type)
+						p->as = AMOVW;
 					break;
 				}
 			}
+		} else
+		if((p->as == AMOVB || p->as == AMOVBU || p->as == AMOVH || p->as == AMOVHU || p->as == AMOVWU)
+		&& regtyp(&p->from) && regtyp(&p->to)){
+			r1 = findpre(r, &p->from);
+			if(r1 != R){
+				p1 = r1->prog;
+				if(p1->as == p->as && p1->to.type == p->from.type)
+					p->as = AMOV;
+			}
 		}
+
 		if(p->as == AMOV || p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
 		if(regtyp(&p->to)) {
 			if(p->from.type == D_CONST)
@@ -441,7 +453,12 @@
 		case AFSQRTD:
 		case AFMOVS:
 		case AFMOVD:
+		case AMOVB:
+		case AMOVBU:
+		case AMOVH:
+		case AMOVHU:
 		case AMOVW:
+		case AMOVWU:
 		case AMOV:
 		case ASXTW:
 			if(p->to.type == v1->type)
@@ -541,12 +558,12 @@
 		switch(t) {
 		case 2:	/* rar, cant split */
 			if(debug['P'])
-				print("; %Drar; return 0\n", v2);
+				print("; %D rar; return 0\n", v2);
 			return 0;
 
 		case 3:	/* set */
 			if(debug['P'])
-				print("; %Dset; return 1\n", v2);
+				print("; %D set; return 1\n", v2);
 			return 1;
 
 		case 1:	/* used, substitute */
@@ -555,9 +572,9 @@
 				if(!debug['P'])
 					return 0;
 				if(t == 4)
-					print("; %Dused+set and f=%d; return 0\n", v2, f);
+					print("; %D used+set and f=%d; return 0\n", v2, f);
 				else
-					print("; %Dused and f=%d; return 0\n", v2, f);
+					print("; %D used and f=%d; return 0\n", v2, f);
 				return 0;
 			}
 			if(copyu(p, v2, v1)) {
@@ -569,7 +586,7 @@
 				print("; sub%D/%D", v2, v1);
 			if(t == 4) {
 				if(debug['P'])
-					print("; %Dused+set; return 1\n", v2);
+					print("; %D used+set; return 1\n", v2);
 				return 1;
 			}
 			break;
@@ -579,7 +596,7 @@
 			if(!f && (t == 2 || t == 3 || t == 4)) {
 				f = 1;
 				if(debug['P'])
-					print("; %Dset and !f; f=%d", v1, f);
+					print("; %D set and !f; f=%d", v1, f);
 			}
 		}
 		if(debug['P'])
--- a/sys/src/cmd/7c/reg.c
+++ b/sys/src/cmd/7c/reg.c
@@ -1058,9 +1058,26 @@
 		p = r->prog;
 
 		if(r->use1.b[z] & bb) {
+			int et = var[bn].etype;
+
 			if(debug['R'])
 				print("%P", p);
 			addreg(&p->from, rn);
+
+			/*
+			 * avoid type converting move instructions when variable type matches.
+			 * the register is already loaded with the correct type conversion
+			 * and type conversing move instructions prevent the peephole optimizer
+			 * from eleminating redundant moves.
+			 */
+			if(p->as == AMOVB && et == TCHAR
+			|| p->as == AMOVBU && et == TUCHAR
+			|| p->as == AMOVH && et == TSHORT
+			|| p->as == AMOVHU && et == TUSHORT
+			|| p->as == AMOVW && (et == TLONG || et == TINT)
+			|| p->as == AMOVWU && (et == TULONG || et == TUINT))
+				p->as = AMOV;
+
 			if(debug['R'])
 				print("\t.c%P\n", p);
 		}