diff options
Diffstat (limited to 'ir')
| -rw-r--r-- | ir/builder.c | 4 | ||||
| -rw-r--r-- | ir/mem2reg.c | 2 | ||||
| -rw-r--r-- | ir/simpl.c | 79 |
3 files changed, 66 insertions, 19 deletions
diff --git a/ir/builder.c b/ir/builder.c index 8fb626c..951c8f4 100644 --- a/ir/builder.c +++ b/ir/builder.c @@ -89,11 +89,11 @@ irbinop(struct function *fn, enum op op, enum irclass k, union ref l, union ref return ZEROREF; break; case Oulte: - if (l.bits == ZEROREF.bits) /* 0 u<= x ==> f */ + if (l.bits == ZEROREF.bits) /* 0 u<= x ==> t */ return ONE; break; case Ougte: - if (r.bits == ZEROREF.bits) /* x u>= 0 ==> f */ + if (r.bits == ZEROREF.bits) /* x u>= 0 ==> t */ return ONE; break; default: diff --git a/ir/mem2reg.c b/ir/mem2reg.c index a1a4132..0bd78ca 100644 --- a/ir/mem2reg.c +++ b/ir/mem2reg.c @@ -262,7 +262,7 @@ mem2reg(struct function *fn) } goto Next; } - if (!ndef) /* slot is read from but never written to */ + if (!ndef && instrnuse[var] > 0) /* slot is read from but never written to */ goto Next; qsort(instruse[var], instrnuse[var], sizeof *instruse[var], cmpuse); @@ -33,6 +33,51 @@ mulk(struct instr *ins, struct block *blk, int *curi) } static int +divmodk(struct instr *ins, struct block *blk, int *curi) +{ + enum op op = ins->op; + enum irclass cls = ins->cls; + vlong iv = intconval(ins->r); + uint nbit = 8 * cls2siz[cls]; + bool neg = (op == Odiv || op == Orem) && iv < 0; + if (ispo2(iv) || (neg && ispo2(-iv))) { /* simple po2 cases */ + union ref temp; + uint s = ilog2(neg ? -iv : iv); + switch (op) { + default: assert(0); + case Oudiv: /* x / 2^s ==> x >> s */ + ins->op = Oslr, ins->r = mkref(RICON, s); + return 1; + case Ourem: /* x % 2^s ==> x & 2^s-1 */ + ins->op = Oand, ins->r = mkintcon(cls, iv - 1); + return 1; + case Odiv: case Orem: + /* have to adjust to round negatives toward zero */ + /* x' = (((x < 0 ? -1 : 0) >>> (Nbit - s)) + x) */ + temp = insertinstr(blk, (*curi)++, mkinstr(Osar, cls, ins->l, mkref(RICON, nbit - 1))); + temp = insertinstr(blk, (*curi)++, mkinstr(Oslr, cls, temp, mkref(RICON, nbit - s))); + temp = insertinstr(blk, (*curi)++, mkinstr(Oadd, cls, ins->l, temp)); + if (op == Odiv) { + /* (-) (x' >> s) */ + struct instr sar = mkinstr(Osar, cls, temp, mkref(RICON, s)); + if (!neg) *ins = sar; + else { + temp = insertinstr(blk, (*curi)++, sar); + ins->op = Oneg, ins->l = temp, ins->r = NOREF; + } + } else { + /* x - (x' & -(2^s)) */ + temp = insertinstr(blk, (*curi)++, mkinstr(Oand, cls, temp, mkintcon(cls, neg ? iv : -iv))); + ins->op = Osub, ins->r = temp; + } + break; + return 0; + } + } + return 0; +} + +static int ins(struct instr *ins, struct block *blk, int *curi) { int narg = opnarg[ins->op]; @@ -40,10 +85,8 @@ ins(struct instr *ins, struct block *blk, int *curi) union ref r = narg == 1 ? irunop(NULL, ins->op, ins->cls, ins->l) : irbinop(NULL, ins->op, ins->cls, ins->l, ins->r); if (r.bits) { - ins->op = Ocopy; - ins->cls = insrescls(*ins); - ins->l = r; - ins->r = NOREF; + *ins = mkinstr(Onop,0,); + replcuses(mkref(RTMP, ins - instrtab), r); return 1; } } @@ -53,6 +96,10 @@ ins(struct instr *ins, struct block *blk, int *curi) if (kisflt(k)) break; if (isnumcon(ins->l)) rswap(ins->l, ins->r); /* put const in rhs */ if (isintcon(ins->r)) return mulk(ins, blk, curi); + break; + case Odiv: case Oudiv: case Orem: case Ourem: + if (kisflt(k)) break; + if (isintcon(ins->r)) return divmodk(ins, blk, curi); } return 0; } @@ -113,15 +160,7 @@ simpl(struct function *fn) struct block **jmpfinal = allocz(fn->passarena, fn->nblk * sizeof *jmpfinal, 0); struct block *blk = fn->entry; - fn->curblk = NULL; do { - for (int i = 0; i < blk->phi.n; ++i) { - - } - for (int i = 0; i < blk->ins.n; ++i) { - inschange += ins(&instrtab[blk->ins.p[i]], blk, &i); - } - /* merge blocks: * @blk: * ... (1) @@ -155,6 +194,17 @@ simpl(struct function *fn) blk->s2 = s->s2; freeblk(fn, s); } + } while ((blk = blk->lnext) != fn->entry); + + if (!(fn->prop & FNUSE)) filluses(fn); + + do { + for (int i = 0; i < blk->phi.n; ++i) {; } + + for (int i = 0; i < blk->ins.n; ++i) { + inschange += ins(&instrtab[blk->ins.p[i]], blk, &i); + } + /* thread jumps.. */ if (!blk->phi.n && !blk->ins.n) { if (blk->jmp.t == Jb && !blk->s2) { @@ -166,10 +216,7 @@ simpl(struct function *fn) } } } while ((blk = blk->lnext) != fn->entry); - if (inschange) { - if (!(fn->prop & FNUSE)) filluses(fn); - copyopt(fn); - } + if (blkchange) { do { if (blk->s1) jmpfind(jmpfinal, &blk->s1); |