ref: 313e4bf78ea365ad29ef9c42b359b7994c566b6d
parent: a3b95d3e567c0ef60f9f1ead26124fb706dec20d
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Jun 12 15:10:12 EDT 2023
7c: elide type converting moves, registerize loads after store from local variables To elide type converting modes, we used findpre() to find the previous instruction generating the source register (to check if type conversion is needed). But findpre() will return nil if it encounters the instruction to be used. What we want is find the instruction that sets/modifies the source regiser for the type converting move. Add a findset() function for this and use instead. The code generator can emit sequences like: MOV reg1, v(SP) MOV v(SP), reg2 We rather get rid of the second load here and convert to: MOV reg1, v(SP) MOV reg1, reg2 And then have copyprop deal with getting rid of the second move. This is what storeprop() does.
--- a/sys/src/cmd/7c/peep.c
+++ b/sys/src/cmd/7c/peep.c
@@ -2,8 +2,11 @@
int xtramodes(Reg*, Adr*);
+Reg* findset(Reg *r, Adr *v);
Reg* findpre(Reg *r, Adr *v);
Reg* findinc(Reg *r, Reg *r2, Adr *v);
+static void
+storeprop(int as, Adr *a, Adr *v, Reg *r);
static int
isu32op(Prog *p)
@@ -142,8 +145,14 @@
t = 0;
for(r=firstr; r!=R; r=r->link) {
p = r->prog;
- if(p->as == ALSL || p->as == ALSR || p->as == AASR ||
- p->as == ALSLW || p->as == ALSRW || p->as == AASRW) {
+
+ /* registerize local loads following stores */
+ if(p->as == AMOV || p->as == AMOVW || p->as == AMOVWU || p->as == AFMOVS || p->as == AFMOVD)
+ if(p->from.type == D_REG && p->to.type == D_OREG && (p->to.name == D_AUTO || p->to.name == D_PARAM))
+ storeprop(p->as, &p->from, &p->to, r->s1);
+
+ if(p->as == ALSL || p->as == ALSR || p->as == AASR
+ || p->as == ALSLW || p->as == ALSRW || p->as == AASRW) {
/*
* elide shift into D_SHIFT operand of subsequent instruction
*/
@@ -153,8 +162,7 @@
}
} else
if(p->as == ASXTW && p->from.type == D_REG && p->to.type == D_REG){
- r1 = findpre(r, &p->from);
- if(r1 != R){
+ if((r1 = findset(r, &p->from)) != R){
p1 = r1->prog;
switch(p1->as){
case AMOVB:
@@ -170,8 +178,7 @@
} else
if((p->as == AMOVB || p->as == AMOVBU || p->as == AMOVH || p->as == AMOVHU || p->as == AMOVWU)
&& (p->from.type == D_REG && p->to.type == D_REG)){
- r1 = findpre(r, &p->from);
- if(r1 != R){
+ if((r1 = findset(r, &p->from)) != R){
p1 = r1->prog;
if(p1->to.type == p->from.type && p1->to.reg == p->from.reg){
if(p1->as == p->as || p->as == AMOVWU && isu32op(p1))
@@ -745,6 +752,48 @@
}
/*
+ * Registerize loads from local variables:
+ *
+ * MOV a, v
+ * ... (a and v not touched)
+ * MOV v, b
+ * ----
+ * MOV a, v
+ * ... (a and v not touched)
+ * MOV a, b
+ */
+static void
+storeprop(int as, Adr *a, Adr *v, Reg *r)
+{
+ Prog *p;
+
+ for(; r != R; r = r->s1) {
+ if(uniqp(r) == R)
+ return;
+
+ p = r->prog;
+ if((as == p->as
+ || (as == AMOV && (p->as == AMOVW || p->as == AMOVWU))
+ || (as == AMOVW && p->as == AMOVWU)
+ || (as == AMOVWU && p->as == AMOVW))
+ && copyas(&p->from, v)){
+ p->from = *a;
+ continue;
+ }
+
+ if(copyu(p, a, A) > 1)
+ return;
+
+ if(p->to.type == D_OREG || p->to.type == D_XPRE || p->to.type == D_XPOST)
+ if(p->to.name == D_NONE || copyas(&p->to, v))
+ return;
+
+ if(r->s2)
+ storeprop(as, a, v, r->s2);
+ }
+}
+
+/*
* ALSL x,y,w
* .. (not use w, not set x y w)
* AXXX w,a,b (a != w)
@@ -865,6 +914,21 @@
}
Reg*
+findset(Reg *r, Adr *v)
+{
+
+ Reg *r1;
+
+ for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
+ if(uniqs(r1) != r)
+ return R;
+ if(copyu(r1->prog, v, A) > 1)
+ return r1;
+ }
+ return R;
+}
+
+Reg*
findpre(Reg *r, Adr *v)
{
Reg *r1;
@@ -1387,7 +1451,7 @@
if(a->type == v->type)
if(a->reg == v->reg)
return 1;
- } else if(v->type == D_CONST) { /* for constprop */
+ } else {
if(a->type == v->type)
if(a->name == v->name)
if(a->sym == v->sym)