diff options
author | Ori Bernstein <ori@eigenstate.org> | 2013-02-09 19:18:43 -0500 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2013-02-09 19:18:43 -0500 |
commit | a13e33b5a6319fb5cc68983b731e6cff821bb458 (patch) | |
tree | d8ad3bb5b05f026be3c144679901874b04b9142a /6/peep.c | |
parent | 3eebcf6c31e23b12d11332f3b424bfe91dc66dcc (diff) | |
download | mc-a13e33b5a6319fb5cc68983b731e6cff821bb458.tar.gz |
Add the start of a peephole optimizer.
It only does one optimization right now -- the elimination
of dumb jumps. Eventually it will do more.
Diffstat (limited to '6/peep.c')
-rw-r--r-- | 6/peep.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/6/peep.c b/6/peep.c new file mode 100644 index 0000000..b7cbcb5 --- /dev/null +++ b/6/peep.c @@ -0,0 +1,86 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <ctype.h> +#include <string.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "parse.h" +#include "opt.h" +#include "asm.h" + + +/* we sometimes leave dead code generated after + * a non-conditional jump. This code scans for + * the non-conditional exit from the BB, and truncates + * at that point */ +static void elimdead(Isel *s, Asmbb *bb) +{ + size_t i; + + for (i = 0; i < bb->ni; i++) { + if (bb->il[i]->op == Ijmp) { + i++; + break; + } + } + bb->ni = i; +} + +/* checks for of dumb jump code. + * nop jumps: + * jmp .l1 + * .l1: + * TODO: check for jumps over jumps. + */ +static void elimnopjmp(Isel *s, Asmbb *bb, size_t idx) +{ + Insn *jmp; + Loc *targ; + Asmbb *nextbb; + size_t i; + + /* skip empty bbs */ + if (!bb->ni) + return; + /* find the target of the last unconditional + * jump in the bb */ + targ = NULL; + if (bb->il[bb->ni - 1]->op == Ijmp) { + jmp = bb->il[bb->ni - 1]; + if (jmp->args[0]->type == Loclbl) + targ = jmp->args[0]; + } + if (!targ) + return; + + /* figure out if it's somewhere in the head of the next bb */ + if (idx < s->nbb) + nextbb = s->bb[idx + 1]; + for (i = 0; i < nextbb->nlbls; i++) { + if (!strcmp(nextbb->lbls[i], targ->lbl)) { + bb->ni--; + break; + } + } +} + +static void bbpeep(Isel *s, Asmbb *bb, size_t idx) +{ + elimdead(s, bb); + elimnopjmp(s, bb, idx); +} + +void peep(Isel *s) +{ + size_t i; + + for (i = 0; i < s->nbb; i++) { + bbpeep(s, s->bb[i], i); + } +} |