diff options
| -rw-r--r-- | amd64/emit.c | 6 | ||||
| -rw-r--r-- | regalloc.c | 11 | ||||
| -rw-r--r-- | ssa.c | 12 | ||||
| -rw-r--r-- | test/fib.c | 11 |
4 files changed, 29 insertions, 11 deletions
diff --git a/amd64/emit.c b/amd64/emit.c index 5b3a298..70386be 100644 --- a/amd64/emit.c +++ b/amd64/emit.c @@ -382,8 +382,8 @@ static void Xmov(uchar **pcode, enum irclass k, struct oper dst, struct oper src {8, PFPR, PFPR, "\xF2\x0F\x10", EN_RR}, /* MOVSD xmm, xmm */ {8, PFPR, PMEM, "\xF2\x0F\x10", EN_RM}, /* MOVSD xmm, m64 */ {8, PMEM, PFPR, "\xF2\x0F\x11", EN_MR}, /* MOVSS m64, xmm */ - {4|8, PGPR, PFPR, "\x66\x0F\x6E", EN_RRX}, /* MOVD/Q r64/32, xmm */ - {4|8, PFPR, PGPR, "\x66\x0F\x6E", EN_RR}, /* MOVD/Q xmm, r64/32 */ + {4|8, PFPR, PGPR, "\x66\x0F\x6E", EN_RR}, /* MOVD/Q xmm, r64/32 */ + {4|8, PGPR, PFPR, "\x66\x0F\x7E", EN_RRX}, /* MOVD/Q r64/32, xmm */ }; static const uchar k2off[] = { [KI4] = 0, @@ -646,7 +646,7 @@ gencopy(uchar **pcode, enum irclass cls, struct block *blk, int curi, struct ope } else { struct oper src = mkimmdatregoper(val); if (memcmp(&dst, &src, sizeof dst) != 0) - Xmov(pcode, cls, dst, src); + Xmov(pcode, cls == KF8 && src.reg < XMM0 ? KI8 : cls, dst, src); } } @@ -7,7 +7,7 @@ static regset gpregset, fpregset; static regset globusage; #define isfpr(reg) in_range((reg), mctarg->fpr0, mctarg->fpr0 + mctarg->nfpr - 1) -#define isgpr(reg) (!isfpr(reg)) +#define isgpr(reg) in_range((reg), mctarg->gpr0, mctarg->gpr0 + mctarg->nfpr - 1) enum { ADEAD, AREG, ASTACK } ; struct alloc { ushort t : 2, a : 14; }; @@ -125,7 +125,7 @@ def(struct rega *ra, struct instr *ins, struct block *blk, int curi) if ((ins->op == Ocopy || ins->inplace) && ins->l.t == RREG) { int hint = ins->l.i; - if (rstest(ra->m.free, hint)) { + if (rstest(ra->m.free, hint) && kisflt(insrescls(*ins)) == isfpr(hint)) { take(ra, reg = hint, mkref(RTMP, var)); assert(ra->m.regs[reg] == var && !rstest(ra->m.free, hint)); } @@ -301,7 +301,8 @@ use(struct rega *ra, struct block *blk, int curi, enum op op, int hint, union re /* for '%x = copy Rx', hint %x to use Rx */ hint = ins->l.i; - if (hint != -1 && !rstest(excl, hint) && rstest(ra->m.free, hint)) { + if (hint != -1 && !rstest(excl, hint) && rstest(ra->m.free, hint) + && kisflt(insrescls(*ins)) == isfpr(hint)) { take(ra, hint, *ref); reg = hint; } else { @@ -568,9 +569,9 @@ regalloc(struct function *fn) /* setup */ if (!fpregset || !gpregset) { for (int i = 0; i < MAXREGS; ++i) { - if (in_range(i, mctarg->fpr0, mctarg->fpr0 + mctarg->nfpr - 1)) + if (isfpr(i)) fpregset = rsset(fpregset, i); - else if (in_range(i, mctarg->gpr0, mctarg->gpr0 + mctarg->ngpr - 1)) + else if (isgpr(i)) gpregset = rsset(gpregset, i); } } @@ -12,11 +12,17 @@ copyopt(struct function *fn) struct use *use, *uend; union ref var = mkref(RTMP, blk->ins.p[i]); struct instr *ins = &instrtab[var.i]; + enum irclass k; if (ins->op == Ocopy) { - assert(ins->l.t != RREG); - - replcuses(var, ins->l); + union ref arg = ins->l; + if (arg.t == RTMP) k = insrescls(instrtab[arg.i]); + else if (arg.t == RICON) k = cls2siz[ins->cls] == 4 ? KI4 : KI8; + else if (arg.t == RXCON) k = isnumcon(arg) ? conht[arg.i].cls : KPTR; + else assert(0); + if (ins->cls != k) continue; + + replcuses(var, arg); *ins = mkinstr(Onop,0,); deluses(var.i); } @@ -13,6 +13,16 @@ unsigned fibr(unsigned x) { return fibr(x-1) + fibr(x-2); } +double fibf(unsigned x) { + double r = 0., q = 1.; + while (x-- > 1) { + double s = r + q; + r = q; + q = s; + } + return q; +} + int atoi(const char *); int printf(const char *, ...); @@ -20,6 +30,7 @@ int main(int argc, char **argv) { unsigned n = argv[1] ? atoi(argv[1]) : 10; printf("fib(%u) = %u\n", n, fib(n)); printf("fibr(%u) = %u\n", n, fibr(n)); + printf("fibf(%u) = %g\n", n, fibf(n)); } /* vim:set ts=3 sw=3 expandtab: */ |