~mcf/cproc

qbe: Avoid redundant leaf ceq in switch (v2) v1 PROPOSED

Roland Paterson-Jones: 1
 qbe: Avoid redundant leaf ceq in switch (v2)

 1 files changed, 10 insertions(+), 4 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~mcf/cproc/patches/55502/mbox | git am -3
Learn more about email & git

[PATCH] qbe: Avoid redundant leaf ceq in switch (v2) Export this patch

Thread existing checked ranges through casesearch() in order
to avoid generating redundant comparisons/blocks for unit
range.

One minor improvement to previous patch - treat 0 case
specially (we could do the same at the max val side but that
seems unlikely to trigger in real code).

Previously posted that errors were encountered with v1 of
the patch; however I believe this was due to the bad 'TLNOT'
patch, and not this one.
---
 qbe.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/qbe.c b/qbe.c
index 33d6b71..5c2f232 100644
--- a/qbe.c
+++ b/qbe.c
@@ -1031,7 +1031,7 @@ funcinit(struct func *func, struct decl *d, struct init *init, bool hasinit)
}

static void
casesearch(struct func *f, int class, struct value *v, struct switchcase *c, struct block *defaultlabel)
casesearch(struct func *f, int class, struct value *v, struct switchcase *c, struct block *defaultlabel, struct switchcase *cl, struct switchcase *cr)
{
	struct value *res, *key;
	struct block *label[3];
@@ -1040,6 +1040,12 @@ casesearch(struct func *f, int class, struct value *v, struct switchcase *c, str
		funcjmp(f, defaultlabel);
		return;
	}
	if (cr && cr->node.key - c->node.key == 1) {
		if (c->node.key == 0 || (cl && c->node.key - cl->node.key == 1)) {
			funcjmp(f, c->body);
			return;
		}
	}
	label[0] = mkblock("switch_ne");
	label[1] = mkblock("switch_lt");
	label[2] = mkblock("switch_gt");
@@ -1052,15 +1058,15 @@ casesearch(struct func *f, int class, struct value *v, struct switchcase *c, str
	res = funcinst(f, class == 'w' ? ICULTW : ICULTL, 'w', v, key);
	funcjnz(f, res, NULL, label[1], label[2]);
	funclabel(f, label[1]);
	casesearch(f, class, v, c->node.child[0], defaultlabel);
	casesearch(f, class, v, c->node.child[0], defaultlabel, cl, c);
	funclabel(f, label[2]);
	casesearch(f, class, v, c->node.child[1], defaultlabel);
	casesearch(f, class, v, c->node.child[1], defaultlabel, c, cr);
}

void
funcswitch(struct func *f, struct value *v, struct switchcases *c, struct block *defaultlabel)
{
	casesearch(f, qbetype(c->type).base, v, c->root, defaultlabel);
	casesearch(f, qbetype(c->type).base, v, c->root, defaultlabel, 0, 0);
}

/* emit */
-- 
2.34.1