ref: a13e33b5a6319fb5cc68983b731e6cff821bb458
parent: 3eebcf6c31e23b12d11332f3b424bfe91dc66dcc
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Feb 9 14:18:43 EST 2013
Add the start of a peephole optimizer. It only does one optimization right now -- the elimination of dumb jumps. Eventually it will do more.
--- a/6/Makefile
+++ b/6/Makefile
@@ -3,6 +3,7 @@
OBJ=isel.o \
locs.o \
main.o \
+ peep.o \
ra.o \
simp.o \
--- a/6/asm.h
+++ b/6/asm.h
@@ -209,6 +209,8 @@
extern size_t modesize[]; /* mode size table */
void regalloc(Isel *s);
+/* machine dependent optimization */
+void peep(Isel *s);
/* useful functions */
size_t tysize(Type *t);
--- /dev/null
+++ b/6/peep.c
@@ -1,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);
+ }
+}