summaryrefslogtreecommitdiff
path: root/6
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-08-23 15:12:42 -0700
committerOri Bernstein <ori@eigenstate.org>2015-08-23 15:12:42 -0700
commitf90519332a6d24444a54c2b0943f705e8579550f (patch)
tree98bb53204bbe193229954add68840ae7d68d2b80 /6
parentcf9651df0886dc8a4c0fbc6da8488606e1e85c31 (diff)
parent3dc71f6baaf6ff6a7e5a41fd89ea3ec2c7bdf88c (diff)
downloadmc-f90519332a6d24444a54c2b0943f705e8579550f.tar.gz
Merge branch 'peephole-opt'
Diffstat (limited to '6')
-rw-r--r--6/Makefile1
-rw-r--r--6/asm.h3
-rw-r--r--6/isel.c1
-rw-r--r--6/peep.c89
4 files changed, 94 insertions, 0 deletions
diff --git a/6/Makefile b/6/Makefile
index 07779a6..6055a80 100644
--- a/6/Makefile
+++ b/6/Makefile
@@ -8,6 +8,7 @@ OBJ= \
locs.o \
main.o \
ra.o \
+ peep.o \
simp.o \
typeinfo.o \
diff --git a/6/asm.h b/6/asm.h
index 2a4946a..b18a617 100644
--- a/6/asm.h
+++ b/6/asm.h
@@ -290,6 +290,9 @@ void dbglocprint(FILE *fd, Loc *l, char spec);
void regalloc(Isel *s);
Rclass rclass(Loc *l);
+/* machine dependent optimization */
+void peep(Isel *s);
+
/* useful functions */
size_t tysize(Type *t);
size_t tyalign(Type *t);
diff --git a/6/isel.c b/6/isel.c
index 12f3039..6cc8ab2 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -1041,6 +1041,7 @@ void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab)
}
is->curbb = is->bb[is->nbb - 1];
epilogue(is);
+ peep(is);
regalloc(is);
is->stksz->lit = align(is->stksz->lit, 16);
}
diff --git a/6/peep.c b/6/peep.c
new file mode 100644
index 0000000..f36cdff
--- /dev/null
+++ b/6/peep.c
@@ -0,0 +1,89 @@
+#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 "mi.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 deadcode(Isel *s, Asmbb *bb)
+{
+ size_t i;
+
+ if (!bb)
+ return;
+ 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 nopjmp(Isel *s, Asmbb *bb, size_t idx)
+{
+ Insn *jmp;
+ Loc *targ;
+ Asmbb *nextbb;
+ size_t i;
+
+ /* skip empty bbs */
+ if (!bb || !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 */
+ nextbb = NULL;
+ for (i = idx + 1; i < s->nbb; i++) {
+ nextbb = s->bb[i];
+ if (nextbb)
+ break;
+ }
+ if (!nextbb)
+ return;
+ for (i = 0; i < nextbb->nlbls; i++) {
+ if (!strcmp(nextbb->lbls[i], targ->lbl)) {
+ bb->ni--;
+ break;
+ }
+ }
+}
+
+void peep(Isel *s)
+{
+ size_t i;
+
+ for (i = 0; i < s->nbb; i++) {
+ deadcode(s, s->bb[i]);
+ nopjmp(s, s->bb[i], i);
+ }
+}