ref: 53ec472196f9174d44b44a687c77eae53fe5842a
parent: f889abbd3860cfb5b26bcd791885f6aa149cb7e4
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Jan 3 11:22:53 EST 2016
Optimize register allocator. Make things a bit less glacial -- reduce the amount of bitset iteration that we're doing.
--- a/6/ra.c
+++ b/6/ra.c
@@ -370,9 +370,10 @@
static void alputedge(Isel *s, regid u, regid v)
{
+ if (!s->gadj[u])
+ s->gadj[u] = xalloc(maxregid*sizeof(regid));
+ s->gadj[u][s->ngadj[u]] = v;
s->ngadj[u]++;
- s->gadj[u] = xrealloc(s->gadj[u], s->ngadj[u]*sizeof(regid));
- s->gadj[u][s->ngadj[u] - 1] = v;
}
static void wlput(Loc ***wl, size_t *nwl, Loc *l)
@@ -472,7 +473,10 @@
size_t nu, nd;
size_t i, k, a;
ssize_t j;
- Bitset *live;
+ regid *livesparse;
+ regid *livedense;
+ size_t nlive;
+ regid r;
Asmbb **bb;
size_t nbb;
Insn *insn;
@@ -482,10 +486,35 @@
bb = s->bb;
nbb = s->nbb;
+#define PUT(reg) do { \
+ assert(reg < maxregid); \
+ if (livesparse[reg] >= nlive || livedense[livesparse[reg]] != reg) {\
+ livesparse[reg] = nlive; \
+ livedense[nlive] = reg; \
+ nlive++; \
+ } \
+ } while(0)
+
+#define DEL(reg) do { \
+ assert(reg < maxregid); \
+ regid rtmp; \
+ if (livesparse[reg] < nlive && livedense[livesparse[reg]] == reg) { \
+ rtmp = livedense[nlive - 1]; \
+ livedense[livesparse[reg]] = rtmp; \
+ livesparse[rtmp] = livesparse[reg]; \
+ nlive--; \
+ } \
+ } while(0)
+
+ /* sparse sets are used here because we iterate them. A lot. */
+ livedense = xalloc((maxregid + 1) * sizeof(regid));
+ livesparse = xalloc((maxregid + 1) * sizeof(regid));
for (i = 0; i < nbb; i++) {
if (!bb[i])
continue;
- live = bsdup(bb[i]->liveout);
+ nlive = 0;
+ for (k = 0; bsiter(bb[i]->liveout, &k); k++)
+ PUT(k);
for (j = bb[i]->ni - 1; j >= 0; j--) {
insn = bb[i]->il[j];
nu = uses(insn, u);
@@ -505,16 +534,17 @@
/* moves get special treatment, since we don't want spurious
* edges between the src and dest */
- //iprintf(stdout, insn);
if (ismove(insn)) {
/* live \= uses(i) */
for (k = 0; k < nu; k++) {
/* remove all physical register aliases */
if (bshas(s->prepainted, u[k])) {
- for (a = 0; a < Nmode; a++)
- bsdel(live, regmap[colourmap[u[k]]][a]);
+ for (a = 0; a < Nmode; a++) {
+ r = regmap[colourmap[u[k]]][a];
+ DEL(r);
+ }
} else {
- bsdel(live, u[k]);
+ DEL(u[k]);
}
}
@@ -526,27 +556,36 @@
bsput(s->wlmoveset, insn->uid);
}
/* live = live U def(i) */
- for (k = 0; k < nd; k++)
- bsput(live, d[k]);
+ for (k = 0; k < nd; k++) {
+ PUT(d[k]);
+ }
- for (k = 0; k < nd; k++)
- for (l = 0; bsiter(live, &l); l++)
- addedge(s, d[k], l);
+ for (k = 0; k < nd; k++) {
+ for (l = 0; l < nlive; l++) {
+ addedge(s, d[k], livedense[l]);
+ }
+ }
/* live = use(i) U (live \ def(i)) */
- for (k = 0; k < nd; k++)
- bsdel(live, d[k]);
- for (k = 0; k < nu; k++)
- bsput(live, u[k]);
+ for (k = 0; k < nd; k++) {
+ DEL(d[k]);
+ }
+
+ for (k = 0; k < nu; k++) {
+ PUT(u[k]);
+ }
}
- bsfree(live);
}
+ free(livedense);
+ free(livesparse);
+#undef PUT
+#undef DEL
}
static int adjavail(Isel *s, regid r)
{
- if (bshas(s->coalesced, r))
- return 0;
if (locmap[r]->list == &s->selstk)
+ return 0;
+ if (bshas(s->coalesced, r))
return 0;
return 1;
}