aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-24 22:49:48 +0200
committerlemon <lsof@mailbox.org>2023-06-24 22:49:48 +0200
commit2c9174841434e39ba0a9675946efe25be0d8a168 (patch)
tree150bde400e89f5a502d2d89b1a92cde0a854a622
parent02d7b9d8c67b12f2e105ee56399a1fc633bcbe0f (diff)
backend: don't mixup float and int temps
copy propagation only happens when dataclasses match, register allocator ignores hints if hint register class and instruction class differ, also add mov between int and float regs in amd64/emit
-rw-r--r--amd64/emit.c6
-rw-r--r--regalloc.c11
-rw-r--r--ssa.c12
-rw-r--r--test/fib.c11
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);
}
}
diff --git a/regalloc.c b/regalloc.c
index a49330d..ae81fcf 100644
--- a/regalloc.c
+++ b/regalloc.c
@@ -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);
}
}
diff --git a/ssa.c b/ssa.c
index 4a4ed4d..fc4464b 100644
--- a/ssa.c
+++ b/ssa.c
@@ -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);
}
diff --git a/test/fib.c b/test/fib.c
index eadce03..5fe430a 100644
--- a/test/fib.c
+++ b/test/fib.c
@@ -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: */