ref: 9a34e9a1e2b4817dca56fd7ad3b9b5cbf43bb4fd
parent: 47f1611cbac920df2a365ca4bb39612f18410ba0
author: Ori Bernstein <[email protected]>
date: Mon May 7 05:55:45 EDT 2012
Improve instruction selection. Fix selection of loads and stores a bit.
--- a/8/asm.h
+++ b/8/asm.h
@@ -57,3 +57,9 @@
};
void genasm(Fn *fn);
+
+Loc *loclbl(Loc *l, Node *lbl);
+Loc *locreg(Loc *l, Reg r);
+Loc *locmem(Loc *l, long disp, Reg base, Reg idx, Mode mode);
+Loc *locmeml(Loc *l, char *disp, Reg base, Reg idx, Mode mode);
+Loc *loclit(Loc *l, long val);
--- a/8/isel.c
+++ b/8/isel.c
@@ -41,6 +41,9 @@
#undef Insn
};
+void locprint(FILE *fd, Loc *l);
+void iprintf(FILE *fd, Insn *insn);
+
/* used to decide which operator is appropriate
* for implementing various conditional operators */
struct {
@@ -111,9 +114,12 @@
{
Loc l;
Node *v;
+ size_t stkoff;
+
switch (exprop(n)) {
case Ovar:
- locmem(&l, 0, Reax, Rnone, ModeL);
+ stkoff = (size_t)htget(s->locs, n->expr.args[0]);
+ locmem(&l, stkoff, Resp, Rnone, ModeL);
break;
case Olit:
v = n->expr.args[0];
@@ -211,15 +217,32 @@
lappend(&s->il, &s->ni, i);
}
-void mov(Isel *s, Loc *a, Loc *b)
+void load(Isel *s, Loc *a, Loc *b)
{
- if (a->type == Locreg && b->type == Locreg)
- if (a->reg == b->reg)
- return;
+ assert(a->type == Loclit || a->type == Locmem || a->type == Loclbl);
+ assert(b->type == Locreg);
g(s, Imov, a, b, NULL);
}
+void stor(Isel *s, Loc *a, Loc *b)
+{
+ assert(a->type == Locreg || a->type == Loclit);
+ assert(b->type == Loclit || b->type == Locmem || b->type == Loclbl);
+ g(s, Imov, a, b, NULL);
+}
+Loc inreg(Isel *s, Loc a)
+{
+ Loc r;
+
+ if (a.type == Locreg)
+ return a;
+ r = getreg(s, a.mode);
+ load(s, &a, &r);
+ return r;
+}
+
+
/* If we're testing equality, etc, it's a bit silly
* to generate the test, store it to a bite, expand it
* to the right width, and then test it again. Try to optimize
@@ -258,6 +281,17 @@
g(s, Ijmp, &l2, NULL);
}
+static Loc binop(Isel *s, AsmOp op, Node *x, Node *y)
+{
+ Loc a, b;
+
+ a = selexpr(s, x);
+ b = selexpr(s, y);
+ a = inreg(s, a);
+ g(s, op, &b, &a, NULL);
+ return a;
+}
+
Loc selexpr(Isel *s, Node *n)
{
Loc a, b, c, r;
@@ -266,20 +300,9 @@
args = n->expr.args;
r = (Loc){Locnone, };
switch (exprop(n)) {
- case Oadd:
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- g(s, Iadd, &b, &a, NULL);
- r = b;
- break;
+ case Oadd: r = binop(s, Iadd, args[0], args[1]); break;
+ case Osub: r = binop(s, Isub, args[0], args[1]); break;
- case Osub:
- a = selexpr(s, args[0]);
- b = selexpr(s, args[1]);
- g(s, Iadd, &b, &a, NULL);
- r = b;
- break;
-
case Omul: die("Unimplemented op %s", opstr(exprop(n))); break;
case Odiv: die("Unimplemented op %s", opstr(exprop(n))); break;
case Omod: die("Unimplemented op %s", opstr(exprop(n))); break;
@@ -314,12 +337,19 @@
g(s, Imovz, &c, &r, NULL);
return r;
- case Oasn:
+ case Oasn: /* relabel */
+ case Ostor: /* reg -> mem */
a = selexpr(s, args[0]);
b = selexpr(s, args[1]);
- mov(s, &b, &a);
+ stor(s, &b, &a);
r = b;
break;
+ case Oload: /* mem -> reg */
+ a = selexpr(s, args[0]);
+ b = selexpr(s, args[1]);
+ load(s, &b, &a);
+ r = b;
+ break;
case Ocall: die("Unimplemented op %s", opstr(exprop(n))); break;
case Ocast: die("Unimplemented op %s", opstr(exprop(n))); break;
@@ -331,13 +361,8 @@
break;
case Olit: /* fall through */
- r = loc(s, n);
- break;
case Ovar:
- b = loc(s, n);
- a = getreg(s, mode(args[0]));
- mov(s, &b, &a);
- r = b;
+ r = loc(s, n);
break;
case Olbl:
loclbl(&r, args[0]);
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -11,6 +11,7 @@
#include "parse.h"
#include "gen.h"
+#include "asm.h"
/* takes a list of nodes, and reduces it (and it's subnodes) to a list
@@ -37,6 +38,7 @@
};
Node *simp(Simp *s, Node *n);
+void declare(Simp *s, Node *n);
void append(Simp *s, Node *n)
{
@@ -48,7 +50,61 @@
return 0;
}
-Node *genlbl(void)
+size_t size(Node *n)
+{
+ Type *t;
+
+ if (n->type == Nexpr)
+ t = n->expr.type;
+ else
+ t = n->decl.sym->type;
+
+ switch (t->type) {
+ case Tyvoid:
+ return 1;
+ case Tybool: case Tychar: case Tyint8:
+ case Tybyte: case Tyuint8:
+ return 1;
+ case Tyint16: case Tyuint16:
+ return 2;
+ case Tyint: case Tyint32:
+ case Tyuint: case Tyuint32:
+ case Typtr: case Tyenum:
+ case Tyfunc:
+ return 4;
+
+ case Tyint64: case Tylong:
+ case Tyuint64: case Tyulong:
+ return 8;
+
+ /*end integer types*/
+ case Tyfloat32:
+ return 4;
+ case Tyfloat64:
+ return 8;
+ case Tyvalist:
+ return 4; /* ptr to first element of valist */
+
+ case Tyslice:
+ return 8; /* len; ptr */
+ case Tyarray:
+ case Tytuple:
+ case Tystruct:
+ case Tyunion:
+ die("Sizes for composite types not implemented yet");
+ break;
+ case Tybad:
+ case Tyvar:
+ case Typaram:
+ case Tyname:
+ case Ntypes:
+ die("Type %s does not have size; why did it get down to here?", tystr(t));
+ break;
+ }
+ return -1;
+}
+
+Node *genlbl(void)
{
char buf[128];
static int nextlbl;
@@ -57,7 +113,7 @@
return mklbl(-1, buf);
}
-Node *temp(Node *e)
+Node *temp(Simp *simp, Node *e)
{
char buf[128];
static int nexttmp;
@@ -70,12 +126,13 @@
n = mkname(-1, buf);
s = mksym(-1, n, e->expr.type);
t = mkdecl(-1, s);
+ declare(simp, t);
return mkexpr(-1, Ovar, t, NULL);
}
void jmp(Simp *s, Node *lbl) { append(s, mkexpr(-1, Ojmp, lbl, NULL)); }
-Node *store(Node *t, Node *n) { return mkexpr(-1, Oasn, t, n, NULL); }
-Node *storetmp(Node *n) { return store(temp(n), n); }
+Node *store(Node *t, Node *n) { return mkexpr(-1, Ostor, t, n, NULL); }
+Node *storetmp(Simp *s, Node *n) { return store(temp(s, n), n); }
void cjmp(Simp *s, Node *cond, Node *iftrue, Node *iffalse)
{
@@ -221,7 +278,7 @@
break;
case Oret:
if (n->expr.args[0]) {
- t = storetmp(simp(s, n->expr.args[0]));
+ t = storetmp(s, simp(s, n->expr.args[0]));
append(s, t);
}
jmp(s, s->endlbl);
@@ -229,7 +286,7 @@
default:
if (isimpure(n)) {
v = simp(s, n);
- t = storetmp(v);
+ t = storetmp(s, v);
append(s, t);
r = t;
} else {
@@ -243,6 +300,11 @@
void declare(Simp *s, Node *n)
{
+ Fn *f;
+
+ f = s->fn;
+ htput(f->locs, n, (void*)f->stksz);
+ f->stksz += size(n);
}
Node *simp(Simp *s, Node *n)
--- a/8/simp.c
+++ b/8/simp.c
@@ -16,6 +16,16 @@
static void lowerglobl(Comp *c, char *name, Node *init);
static void lowerfn(Comp *c, char *name, Node *n);
+static ulong ptrhash(void *key)
+{
+ return (ulong)key;
+}
+
+static int ptreq(void *a, void *b)
+{
+ return a == b;
+}
+
Fn *mkfn(char *name)
{
Fn *f;
@@ -23,6 +33,7 @@
f = zalloc(sizeof(Fn));
f->name = strdup(name);
f->isglobl = 1;
+ f->locs = mkht(ptrhash, ptreq);
return f;
}
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -16,7 +16,7 @@
void yyerror(const char *s);
int yylex(void);
-Op binop(int toktype);
+static Op binop(int toktype);
Stab *curscope;
//int n = 0;
%}
@@ -549,7 +549,7 @@
fprintf(stderr, "\n");
}
-Op binop(int tt)
+static Op binop(int tt)
{
Op o;
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -316,9 +316,6 @@
t = unify(n, mkty(-1, Tyvoid), ret);
settype(n, t);
break;
- case Ocjmp:
- die("Should not see cjmp in fe");
- break;
case Ojmp: /* goto void* -> void */
settype(n, mkty(-1, Tyvoid));
break;
@@ -339,8 +336,9 @@
break;
case Olbl: /* :lbl -> void* */
settype(n, mktyptr(n->line, mkty(-1, Tyvoid)));
- case Obad: /* error! */
- case Numops:
+ case Obad: case Numops: case Ocjmp:
+ case Oload: case Ostor:
+ die("Should not see %s in fe", opstr(exprop(n)));
break;
}
}
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -45,7 +45,10 @@
O(Ocast)
O(Oret)
O(Ojmp)
-O(Ocjmp)
O(Ovar)
O(Olit)
O(Olbl)
+/* backend-only */
+O(Ocjmp) /* conditional jump */
+O(Oload) /* load from memory */
+O(Ostor) /* store to memory */