Commit 23fc0ac0 authored by Ken Thompson's avatar Ken Thompson

more code optimization

R=r
OCL=21159
CL=21159
parent 719b0886
...@@ -54,8 +54,7 @@ cgen(Node *n, Node *res) ...@@ -54,8 +54,7 @@ cgen(Node *n, Node *res)
f = 1; // gen thru register f = 1; // gen thru register
switch(n->op) { switch(n->op) {
case OLITERAL: case OLITERAL:
if(isint[n->type->etype]) if(smallintconst(n))
if(n->type->width <= 4)
f = 0; f = 0;
break; break;
case OREGISTER: case OREGISTER:
...@@ -63,7 +62,7 @@ cgen(Node *n, Node *res) ...@@ -63,7 +62,7 @@ cgen(Node *n, Node *res)
break; break;
} }
if(sudoaddable(res, n->type, &addr, &n1)) { if(sudoaddable(res, n->type, &addr)) {
a = optoas(OAS, res->type); a = optoas(OAS, res->type);
if(f) { if(f) {
regalloc(&n2, res->type, N); regalloc(&n2, res->type, N);
...@@ -73,7 +72,7 @@ cgen(Node *n, Node *res) ...@@ -73,7 +72,7 @@ cgen(Node *n, Node *res)
} else } else
p1 = gins(a, n, N); p1 = gins(a, n, N);
p1->to = addr; p1->to = addr;
regfree(&n1); sudoclean();
goto ret; goto ret;
} }
...@@ -101,7 +100,7 @@ cgen(Node *n, Node *res) ...@@ -101,7 +100,7 @@ cgen(Node *n, Node *res)
goto ret; goto ret;
} }
if(sudoaddable(n, res->type, &addr, &n1)) { if(sudoaddable(n, res->type, &addr)) {
a = optoas(OAS, n->type); a = optoas(OAS, n->type);
if(res->op == OREGISTER) { if(res->op == OREGISTER) {
p1 = gins(a, N, res); p1 = gins(a, N, res);
...@@ -113,7 +112,7 @@ cgen(Node *n, Node *res) ...@@ -113,7 +112,7 @@ cgen(Node *n, Node *res)
gins(a, &n2, res); gins(a, &n2, res);
regfree(&n2); regfree(&n2);
} }
regfree(&n1); sudoclean();
goto ret; goto ret;
} }
...@@ -317,11 +316,11 @@ abop: // asymmetric binary ...@@ -317,11 +316,11 @@ abop: // asymmetric binary
regalloc(&n1, nl->type, res); regalloc(&n1, nl->type, res);
cgen(nl, &n1); cgen(nl, &n1);
if(sudoaddable(nr, nl->type, &addr, &n2)) { if(sudoaddable(nr, nl->type, &addr)) {
p1 = gins(a, N, &n1); p1 = gins(a, N, &n1);
p1->from = addr; p1->from = addr;
gmove(&n1, res); gmove(&n1, res);
regfree(&n2); sudoclean();
regfree(&n1); regfree(&n1);
goto ret; goto ret;
} }
...@@ -724,7 +723,7 @@ bgen(Node *n, int true, Prog *to) ...@@ -724,7 +723,7 @@ bgen(Node *n, int true, Prog *to)
a = brcom(a); a = brcom(a);
// make simplest on right // make simplest on right
if(nl->ullman < nr->ullman) { if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
a = brrev(a); a = brrev(a);
r = nl; r = nl;
nl = nr; nl = nr;
...@@ -755,10 +754,16 @@ bgen(Node *n, int true, Prog *to) ...@@ -755,10 +754,16 @@ bgen(Node *n, int true, Prog *to)
break; break;
} }
regalloc(&n1, nl->type, N); regalloc(&n1, nl->type, N);
cgen(nl, &n1); cgen(nl, &n1);
if(smallintconst(nr)) {
gins(optoas(OCMP, nr->type), &n1, nr);
patch(gbranch(a, nr->type), to);
regfree(&n1);
break;
}
regalloc(&n2, nr->type, N); regalloc(&n2, nr->type, N);
cgen(nr, &n2); cgen(nr, &n2);
......
...@@ -199,7 +199,9 @@ void tempname(Node*, Type*); ...@@ -199,7 +199,9 @@ void tempname(Node*, Type*);
Plist* newplist(void); Plist* newplist(void);
int isfat(Type*); int isfat(Type*);
void setmaxarg(Type*); void setmaxarg(Type*);
int sudoaddable(Node*, Type*, Addr*, Node*); int smallintconst(Node*);
void sudoclean(void);
int sudoaddable(Node*, Type*, Addr*);
/* /*
* list.c * list.c
......
...@@ -113,12 +113,16 @@ ginit(void) ...@@ -113,12 +113,16 @@ ginit(void)
reg[i] = 0; reg[i] = 0;
for(i=D_X0; i<=D_X7; i++) for(i=D_X0; i<=D_X7; i++)
reg[i] = 0; reg[i] = 0;
// reg[D_DI]++; // for movstring
// reg[D_SI]++; // for movstring
reg[D_AX]++; // for divide reg[D_AX]++; // for divide
reg[D_CX]++; // for shift reg[D_CX]++; // for shift
reg[D_DI]++; // for movstring
reg[D_DX]++; // for divide reg[D_DX]++; // for divide
reg[D_SI]++; // for movstring
reg[D_SP]++; // for stack reg[D_SP]++; // for stack
reg[D_R14]++; // reserved for m
reg[D_R15]++; // reserved for u
} }
void void
...@@ -126,12 +130,16 @@ gclean(void) ...@@ -126,12 +130,16 @@ gclean(void)
{ {
int i; int i;
// reg[D_DI]--; // for movstring
// reg[D_SI]--; // for movstring
reg[D_AX]--; // for divide reg[D_AX]--; // for divide
reg[D_CX]--; // for shift reg[D_CX]--; // for shift
reg[D_DI]--; // for movstring
reg[D_DX]--; // for divide reg[D_DX]--; // for divide
reg[D_SI]--; // for movstring
reg[D_SP]--; // for stack reg[D_SP]--; // for stack
reg[D_R14]--; // reserved for m
reg[D_R15]--; // reserved for u
for(i=D_AX; i<=D_R15; i++) for(i=D_AX; i<=D_R15; i++)
if(reg[i]) if(reg[i])
yyerror("reg %R left allocated\n", i); yyerror("reg %R left allocated\n", i);
...@@ -1810,59 +1818,270 @@ dotoffset(Node *n, int *oary, Node **nn) ...@@ -1810,59 +1818,270 @@ dotoffset(Node *n, int *oary, Node **nn)
} }
int int
sudoaddable(Node *n, Type *t, Addr *a, Node *reg) smallintconst(Node *n)
{ {
int et, o, i; if(n->op == OLITERAL)
switch(simtype[n->type->etype]) {
case TINT8:
case TUINT8:
case TINT16:
case TUINT16:
case TINT32:
case TUINT32:
case TBOOL:
case TPTR32:
return 1;
}
return 0;
}
enum
{
ODynam = 1<<0,
OPtrto = 1<<1,
};
static Node clean[20];
static int cleani = 0;
void
sudoclean(void)
{
if(clean[cleani-1].op != OEMPTY)
regfree(&clean[cleani-1]);
if(clean[cleani-2].op != OEMPTY)
regfree(&clean[cleani-2]);
cleani -= 2;
}
int
sudoaddable(Node *n, Type *t, Addr *a)
{
int et, o, i, w;
int oary[10]; int oary[10];
Node n1, *nn; vlong v;
Node n0, n1, n2, *nn, *l, *r;
Node *reg, *reg1;
Prog *p1;
// make a cleanup slot
cleani += 2;
reg = &clean[cleani-1];
reg1 = &clean[cleani-2];
reg->op = OEMPTY;
reg1->op = OEMPTY;
if(n->type == T || t == T) if(n->type == T || t == T)
return 0; goto no;
et = simtype[n->type->etype]; et = simtype[n->type->etype];
if(et != simtype[t->etype]) if(et != simtype[t->etype])
return 0; goto no;
switch(n->op) { switch(n->op) {
default: default:
return 0; goto no;
case ODOT: case ODOT:
case ODOTPTR: case ODOTPTR:
o = dotoffset(n, oary, &nn); goto odot;
if(nn == N)
return 0; case OINDEXPTR:
goto no;
if(0) { case OINDEX:
dump("\nXX", n); goto oindex;
dump("YY", nn); }
for(i=0; i<o; i++)
print(" %d", oary[i]); odot:
print("\n"); o = dotoffset(n, oary, &nn);
return 0; if(nn == N)
} goto no;
if(0) {
dump("\nXX", n);
dump("YY", nn);
for(i=0; i<o; i++)
print(" %d", oary[i]);
print("\n");
goto no;
}
regalloc(reg, types[tptr], N);
n1 = *reg;
n1.op = OINDREG;
if(oary[0] >= 0) {
agen(nn, reg);
n1.xoffset = oary[0];
} else {
cgen(nn, reg);
n1.xoffset = -(oary[0]+1);
}
for(i=1; i<o; i++) {
if(oary[i] >= 0)
fatal("cant happen");
gins(AMOVQ, &n1, reg);
n1.xoffset = -(oary[i]+1);
}
a->type = D_NONE;
a->index = D_NONE;
naddr(&n1, a);
goto yes;
oindex:
l = n->left;
r = n->right;
if(l->ullman >= UINF || r->ullman >= UINF)
goto no;
// set o to type of array
o = 0;
if(isptr[l->type->etype]) {
o += OPtrto;
if(l->type->type->etype != TARRAY)
fatal("not ptr ary");
if(l->type->type->bound < 0)
o += ODynam;
} else {
if(l->type->etype != TARRAY)
fatal("not ary");
if(l->type->bound < 0)
o += ODynam;
}
w = n->type->width;
if(w == 0)
fatal("index is zero width");
if(whatis(r) == Wlitint)
goto oindex_const;
switch(w) {
default:
goto no;
case 1:
case 2:
case 4:
case 8:
break;
}
// load the array (reg)
if(l->ullman > r->ullman) {
regalloc(reg, types[tptr], N); regalloc(reg, types[tptr], N);
n1 = *reg; if(o & OPtrto)
n1.op = OINDREG; cgen(l, reg);
if(oary[0] >= 0) { else
agen(nn, reg); agen(l, reg);
n1.xoffset = oary[0]; }
// load the index (reg1)
t = types[TUINT64];
if(issigned[r->type->etype])
t = types[TINT64];
regalloc(reg1, t, N);
cgen(r, reg1);
// load the array (reg)
if(l->ullman <= r->ullman) {
regalloc(reg, types[tptr], N);
if(o & OPtrto)
cgen(l, reg);
else
agen(l, reg);
}
// check bounds
if(!debug['B']) {
if(o & ODynam) {
n2 = *reg;
n2.op = OINDREG;
n2.type = types[tptr];
n2.xoffset = offsetof(Array, nel);
} else { } else {
cgen(nn, reg); nodconst(&n2, types[TUINT64], l->type->bound);
n1.xoffset = -(oary[0]+1); if(o & OPtrto)
nodconst(&n2, types[TUINT64], l->type->type->bound);
} }
gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
gins(ACALL, N, throwindex);
patch(p1, pc);
}
if(o & ODynam) {
n2 = *reg;
n2.op = OINDREG;
n2.type = types[tptr];
n2.xoffset = offsetof(Array, array);
gmove(&n2, reg);
}
for(i=1; i<o; i++) { naddr(reg1, a);
if(oary[i] >= 0) a->offset = 0;
fatal("cant happen"); a->scale = w;
gins(AMOVQ, &n1, reg); a->index = a->type;
n1.xoffset = -(oary[i]+1); a->type = reg->val.u.reg + D_INDIR;
goto yes;
oindex_const:
// index is constant
// can check statically and
// can multiply by width statically
regalloc(reg, types[tptr], N);
if(o & OPtrto)
cgen(l, reg);
else
agen(l, reg);
v = mpgetfix(r->val.u.xval);
if(o & ODynam) {
if(!debug['B']) {
n1 = *reg;
n1.op = OINDREG;
n1.type = types[tptr];
n1.xoffset = offsetof(Array, nel);
nodconst(&n2, types[TUINT64], v);
gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
gins(ACALL, N, throwindex);
patch(p1, pc);
} }
a->type = D_NONE; n1 = *reg;
a->index = D_NONE; n1.op = OINDREG;
naddr(&n1, a); n1.type = types[tptr];
break; n1.xoffset = offsetof(Array, array);
gmove(&n1, reg);
} else
if(!debug['B']) {
if(v < 0) {
yyerror("out of bounds on array");
} else
if(o & OPtrto) {
if(v >= l->type->type->bound)
yyerror("out of bounds on array");
} else
if(v >= l->type->bound) {
yyerror("out of bounds on array");
}
} }
n2 = *reg;
n2.op = OINDREG;
n2.xoffset = v*w;
a->type = D_NONE;
a->index = D_NONE;
naddr(&n2, a);
goto yes;
yes:
return 1; return 1;
no:
sudoclean();
return 0;
} }
...@@ -102,6 +102,7 @@ regopt(Prog *firstp) ...@@ -102,6 +102,7 @@ regopt(Prog *firstp)
if(first) { if(first) {
fmtinstall('Q', Qconv); fmtinstall('Q', Qconv);
exregoffset = D_R13; // R14,R15 are external
first = 0; first = 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment