shithub: mc

Download patch

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 */