mirror of
git://c9x.me/qbe.git
synced 2026-04-05 09:59:47 +00:00
new simplcfg pass
Useful for ifopt to match more often. Empty blocks are fused and conditional jumps on empty blocks with the same successor (and no phis in the successor) are collapsed.
This commit is contained in:
parent
c6336557da
commit
e8365dd0a2
1
all.h
1
all.h
@ -560,6 +560,7 @@ void simpljmp(Fn *);
|
|||||||
int reaches(Fn *, Blk *, Blk *);
|
int reaches(Fn *, Blk *, Blk *);
|
||||||
int reachesnotvia(Fn *, Blk *, Blk *, Blk *);
|
int reachesnotvia(Fn *, Blk *, Blk *, Blk *);
|
||||||
int ifgraph(Blk *, Blk **, Blk **, Blk **);
|
int ifgraph(Blk *, Blk **, Blk **, Blk **);
|
||||||
|
void simplcfg(Fn *);
|
||||||
|
|
||||||
/* mem.c */
|
/* mem.c */
|
||||||
void promote(Fn *);
|
void promote(Fn *);
|
||||||
|
|||||||
121
cfg.c
121
cfg.c
@ -441,3 +441,124 @@ ifgraph(Blk *ifb, Blk **pthenb, Blk **pelseb, Blk **pjoinb)
|
|||||||
*pjoinb = s1->s1;
|
*pjoinb = s1->s1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct Jmp Jmp;
|
||||||
|
|
||||||
|
struct Jmp {
|
||||||
|
int type;
|
||||||
|
Ref arg;
|
||||||
|
Blk *s1, *s2;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
jmpeq(Jmp *a, Jmp *b)
|
||||||
|
{
|
||||||
|
return a->type == b->type && req(a->arg, b->arg)
|
||||||
|
&& a->s1 == b->s1 && a->s2 == b->s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
jmpnophi(Jmp *j)
|
||||||
|
{
|
||||||
|
if (j->s1 && j->s1->phi)
|
||||||
|
return 0;
|
||||||
|
if (j->s2 && j->s2->phi)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* require cfg rpo, breaks use */
|
||||||
|
void
|
||||||
|
simplcfg(Fn *fn)
|
||||||
|
{
|
||||||
|
Ins cpy, *i;
|
||||||
|
Blk *b, *bb, **pb;
|
||||||
|
Jmp *jmp, *j, *jj;
|
||||||
|
Phi *p;
|
||||||
|
int *empty, done;
|
||||||
|
uint n;
|
||||||
|
|
||||||
|
if (debug['C']) {
|
||||||
|
fprintf(stderr, "\n> Before CFG simplification:\n");
|
||||||
|
printfn(fn, stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpy = (Ins){.op = Ocopy};
|
||||||
|
for (b=fn->start; b; b=b->link)
|
||||||
|
if (b->npred == 1) {
|
||||||
|
bb = b->pred[0];
|
||||||
|
for (p=b->phi; p; p=p->link) {
|
||||||
|
cpy.cls = p->cls;
|
||||||
|
cpy.to = p->to;
|
||||||
|
cpy.arg[0] = phiarg(p, bb);
|
||||||
|
addins(&bb->ins, &bb->nins, &cpy);
|
||||||
|
}
|
||||||
|
b->phi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jmp = emalloc(fn->nblk * sizeof jmp[0]);
|
||||||
|
empty = emalloc(fn->nblk * sizeof empty[0]);
|
||||||
|
for (b=fn->start; b; b=b->link) {
|
||||||
|
jmp[b->id].type = b->jmp.type;
|
||||||
|
jmp[b->id].arg = b->jmp.arg;
|
||||||
|
jmp[b->id].s1 = b->s1;
|
||||||
|
jmp[b->id].s2 = b->s2;
|
||||||
|
empty[b->id] = !b->phi;
|
||||||
|
for (i=b->ins; i<&b->ins[b->nins]; i++)
|
||||||
|
if (i->op != Onop || i->op != Odbgloc) {
|
||||||
|
empty[b->id] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
done = 1;
|
||||||
|
for (b=fn->start; b; b=b->link) {
|
||||||
|
if (b->id == -1u)
|
||||||
|
continue;
|
||||||
|
j = &jmp[b->id];
|
||||||
|
if (j->type == Jjmp && j->s1->npred == 1) {
|
||||||
|
assert(!j->s1->phi);
|
||||||
|
addbins(&b->ins, &b->nins, j->s1);
|
||||||
|
empty[b->id] &= empty[j->s1->id];
|
||||||
|
jj = &jmp[j->s1->id];
|
||||||
|
pb = (Blk*[]){jj->s1, jj->s2, 0};
|
||||||
|
for (; (bb=*pb); pb++)
|
||||||
|
for (p=bb->phi; p; p=p->link) {
|
||||||
|
n = phiargn(p, j->s1);
|
||||||
|
p->blk[n] = b;
|
||||||
|
}
|
||||||
|
j->s1->id = -1u;
|
||||||
|
*j = *jj;
|
||||||
|
done = 0;
|
||||||
|
}
|
||||||
|
else if (j->type == Jjnz
|
||||||
|
&& empty[j->s1->id] && empty[j->s2->id]
|
||||||
|
&& jmpeq(&jmp[j->s1->id], &jmp[j->s2->id])
|
||||||
|
&& jmpnophi(&jmp[j->s1->id])) {
|
||||||
|
*j = jmp[j->s1->id];
|
||||||
|
done = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!done);
|
||||||
|
|
||||||
|
for (b=fn->start; b; b=b->link)
|
||||||
|
if (b->id != -1u) {
|
||||||
|
j = &jmp[b->id];
|
||||||
|
b->jmp.type = j->type;
|
||||||
|
b->jmp.arg = j->arg;
|
||||||
|
b->s1 = j->s1;
|
||||||
|
b->s2 = j->s2;
|
||||||
|
assert(!j->s1 || j->s1->id != -1u);
|
||||||
|
assert(!j->s2 || j->s2->id != -1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillcfg(fn);
|
||||||
|
free(empty);
|
||||||
|
free(jmp);
|
||||||
|
|
||||||
|
if (debug['C']) {
|
||||||
|
fprintf(stderr, "\n> After CFG simplification:\n");
|
||||||
|
printfn(fn, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user