[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