commit 536603d56b036bcf87e0678ce8c5e760d9b17b97
parent 9b258f5adb6f13f217a6e551ac05d30574ecb168
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 31 Dec 2024 15:11:33 +0100
cc2: First implementation of direct switch
The fastest implementation of a switch is using a jump table
although it has some initial overhead and it can be very
inneficient in space in some cases. For this reason it is used
only in some cases. This commit is a first step that dumps
a jump table but it still don't use it.
Diffstat:
2 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/src/cmd/scc-cc/cc2/cfg.c b/src/cmd/scc-cc/cc2/cfg.c
@@ -302,6 +302,7 @@ swtch_if(Node *idx)
for (np = idx->next; ; np = next) {
next = np->next;
+
switch (np->op) {
case OESWITCH:
if (!deflabel)
@@ -328,28 +329,71 @@ swtch_if(Node *idx)
}
static Node *
+swtch_dir(Node *np, int n, TINT min, TINT max)
+{
+ Node aux, *p, *defnode;
+ Node **its, **zero, **ip;
+ Symbol *tbl;
+
+ its = xcalloc(n, sizeof(*its));
+ zero = its;
+ if (min < 0)
+ zero -= min;
+
+ for (p = np->next; p->op != OESWITCH; p = p->next) {
+ if (p->op == ODEFAULT)
+ defnode = p;
+ else
+ its[p->left->u.i] = p;
+ p->type = ptrtype;
+ p->op = OLABEL;
+ }
+ np->next = p->next;
+
+ for (ip = its; ip < &its[n]; ++ip) {
+ if (*ip == NULL)
+ *ip = defnode;
+ }
+
+ tbl = getsym(TMPSYM);
+ tbl->kind = SLOCAL;
+ tbl->type = ptrtype;
+ tbl->type.flags |= INITF;
+
+ defglobal(tbl);
+ for (ip = its; ip < &its[n]; ++ip)
+ data(*ip);
+ endinit();
+}
+
+static Node *
swtch(Node *np)
{
int n;
- TINT min, max, val;
+ TINT min, max, range, val;
Node *p, *def = NULL;
min = TINT_MAX;
- min = max = n = 0;
+ max = n = 0;
for (p = np->next; p->op != OESWITCH; p = p->next) {
- if (p->op == ODEFAULT) {
- def = np;
- } else {
- val = np->left->u.i;
+ if (p->op != ODEFAULT) {
+ val = p->left->u.i;
if (val > max)
max = val;
if (val < min)
min = val;
+ ++n;
}
- ++n;
}
- return swtch_if(np);
+ if (n < 4)
+ return swtch_if(np);
+
+ range = max - min + 1;
+ if (range == n)
+ return swtch_dir(np, range, min, max);
+
+ abort();
}
Node *
diff --git a/src/cmd/scc-cc/cc2/z80-scc/code.c b/src/cmd/scc-cc/cc2/z80-scc/code.c
@@ -139,6 +139,7 @@ emittree(Node *np)
case OADDR:
emittree(np->left);
break;
+ case OLABEL:
case OMEM:
fputs(symname(np->u.sym), stdout);
break;