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);
}