aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-20 09:45:26 +0200
committerlemon <lsof@mailbox.org>2023-06-20 09:45:26 +0200
commit945d17aff2aa92dd1fbb0304d4ee7ab5ea6ce496 (patch)
treebb63bc06b372058d0931ef4a2ad915836b64ce96
parent981906a54e6c8dd727b7b6be2a428c547877ef78 (diff)
fix cls logic for comparison instrs
previously instr.cls always represented the output dataclass. this doesn't work for comparisons because we know the output is always a boolean integer and we care about the actual comparison dataclass. so now .cls represents the operation dataclass, which matches the result class except for comparisons where the result is always KI4V
-rw-r--r--amd64/emit.c3
-rw-r--r--amd64/isel.c2
-rw-r--r--c.c2
-rw-r--r--ir.h6
-rw-r--r--irdump.c11
-rw-r--r--regalloc.c16
6 files changed, 23 insertions, 17 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index c7c6258..21a59b7 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -529,10 +529,11 @@ Xjcc(uchar **pcode, enum cc cc, struct block *dst)
}
static void
-Xsetcc(uchar **pcode, enum cc cc, int reg)
+Xsetcc(uchar **pcode, enum cc cc, enum reg reg)
{
int rex = 0;
assert(in_range(cc, 0x0, 0xF));
+ assert(in_range(reg, RAX, R15));
if (in_range(reg, RSP, RDI)) rex = 0x40;
rex |= (reg >> 3); /* REX.B */
diff --git a/amd64/isel.c b/amd64/isel.c
index a613f53..10ff5ea 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -355,7 +355,7 @@ amd64_isel(struct function *fn)
for (i = 0; i < blk->ins.n; ++i) {
struct instr *ins = &instrtab[blk->ins.p[i]];
sel(fn, ins, blk, &i);
- if (ins->op < arraylength(opflags) && kisint(ins->cls)) {
+ if (ins->op < arraylength(opflags) && kisint(insrescls(*ins))) {
if (opflags[ins->op] & ZF) iflagsrc = ins - instrtab;
else if (opflags[ins->op] & CLOBF) iflagsrc = -1;
}
diff --git a/c.c b/c.c
index 6db23be..c3297e8 100644
--- a/c.c
+++ b/c.c
@@ -1520,7 +1520,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
if (discard) return NOREF;
ins.l = cvt(fn, ty.t, sub[0].ty.t, ins.l);
ins.r = cvt(fn, ty.t, sub[1].ty.t, ins.r);
- ins.cls = cls;
+ ins.cls = type2cls[ty.t];
return addinstr(fn, ins);
case ESET:
assert(isscalar(ex->ty));
diff --git a/ir.h b/ir.h
index 3858d0d..72a0bd5 100644
--- a/ir.h
+++ b/ir.h
@@ -91,7 +91,7 @@ enum op {
#undef _
};
-#define oiscmp(o) in_range(o, Oequ, Oulte)
+#define oiscmp(o) in_range(o, Oequ, Ougte)
#define oisalloca(o) in_range(o, Oalloca1, Oalloca16)
#define oisstore(o) in_range(o, Ostore1, Ostore8)
#define oisload(o) in_range(o, Oloads1, Oloadf8)
@@ -105,7 +105,8 @@ enum intrin {
};
struct instr {
- uchar op, cls;
+ uchar op,
+ cls; /* operation data class; also result class except for cmp ops (always i4) */
uchar skip : 1; /* ignore during codegen: forms part of one machine instruction */
uchar inplace : 1; /* set (by isel) for instructions which modify its first arg in place */
uchar reg; /* 0 -> no reg; else reg + 1 */
@@ -189,6 +190,7 @@ extern struct calltab {vec_of(struct call);} calltab;
extern struct phitab {vec_of(struct phi);} phitab;
extern struct dattab {vec_of(struct irdat);} dattab;
extern struct addr addrht[];
+#define insrescls(ins) (oiscmp((ins).op) ? KI4 : (ins).cls)
#define NOREF ((union ref) {0})
#define ZEROREF ((union ref) {{ RICON, 0 }})
#define mkref(t, x) ((union ref) {{ (t), (x) }})
diff --git a/irdump.c b/irdump.c
index cd7468f..f1a64f5 100644
--- a/irdump.c
+++ b/irdump.c
@@ -166,15 +166,18 @@ dumpinst(const struct instr *ins)
if (ins->op == Omove) {
efmt("move %s ", clsname[ins->cls]);
} else {
+ enum irclass cls = insrescls(*ins);
if (ins->reg) {
- if (ins->cls)
- efmt("%s ", clsname[ins->cls]);
+ if (cls)
+ efmt("%s ", clsname[cls]);
efmt("%s = ", mctarg->rnames[ins->reg - 1]);
- } else if (ins->cls) {
- efmt("%s %%%d", clsname[ins->cls], ins - instrtab);
+ } else if (cls) {
+ efmt("%s %%%d", clsname[cls], ins - instrtab);
efmt(" = ");
}
efmt("%s ", opnames[ins->op]);
+ if (oiscmp(ins->op))
+ efmt("%s ", clsname[ins->cls]);
}
for (i = 0; i < opnarg[ins->op]; ++i) {
if (i) efmt(", ");
diff --git a/regalloc.c b/regalloc.c
index ed5af2c..1b3b765 100644
--- a/regalloc.c
+++ b/regalloc.c
@@ -61,8 +61,8 @@ def(struct rega *ra, struct instr *ins, struct block *blk, int curi)
assert(ra->regs[reg].bits == mkref(RTMP, var).bits);
} else if (alloc->t == ASTACK) {
/* unspill, insert 'store [slot], reg' */
- int reg = allocreg(ra, ins->cls, mkref(RTMP, var), -1);
- struct instr store = mkinstr(Ostore1 + ilog2(cls2siz[ins->cls]), 0,
+ int reg = allocreg(ra, insrescls(*ins), mkref(RTMP, var), -1);
+ struct instr store = mkinstr(Ostore1 + ilog2(cls2siz[insrescls(*ins)]), 0,
mkref(RICON, alloc->a*8), mkref(RREG, reg));
DBG("-- unspill %%%d s%d -> %s\n", var, alloc->a, mctarg->rnames[ins->reg+1]);
addstkslotref(insertinstr(blk, ++curi, store));
@@ -151,7 +151,7 @@ spill(struct rega *ra, int reg, struct block *blk, int curi) {
DBG("-- spill %%%d %s -> s%d\n", var, mctarg->rnames[reg], s);
instrtab[var].reg = 0;
/* insert 'reg = load [slot]' */
- load = mkinstr(Oloads1 + 2*ilog2(cls2siz[instrtab[var].cls]), instrtab[var].cls, mkref(RICON, s*8));
+ load = mkinstr(Oloads1 + 2*ilog2(cls2siz[insrescls(instrtab[var])]), insrescls(instrtab[var]), mkref(RICON, s*8));
load.reg = reg+1;
addstkslotref(insertinstr(blk, ++curi, load));
freereg(ra, reg);
@@ -184,7 +184,7 @@ forcetake(struct rega *ra, int reg, union ref ref, struct block *blk, int curi)
int rename = allocreg(ra, isgpr(reg) ? KI4 : KF4, ra->regs[reg], excl);
if (ccopt.dbg.r)DBG("-- rename %%%d %s -> %s\n", var, mctarg->rnames[reg], mctarg->rnames[rename]);
/* introduce move from rename -> original (since we allocate backwards) */
- insertinstr(blk, ++curi, mkmove(instrtab[var].cls, reg, rename));
+ insertinstr(blk, ++curi, mkmove(insrescls(instrtab[var]), reg, rename));
instrtab[var].reg = rename+1;
ra->regs[rename] = mkref(RTMP, var);
bsset(globusage, rename);
@@ -230,12 +230,12 @@ use(struct rega *ra, struct block *blk, int curi, enum op op, int hint, union re
take(ra, hint, *ref);
ins->reg = hint + 1;
} else {
- ins->reg = allocreg(ra, ins->cls, *ref, excl) + 1;
+ ins->reg = allocreg(ra, insrescls(*ins), *ref, excl) + 1;
}
if (s >= 0) {
/* unspill, insert 'store [slot], reg' */
DBG("-- unspill %%%d s%d -> %s\n", ref->i, s, mctarg->rnames[ins->reg-1]);
- struct instr store = mkinstr(Ostore1 + ilog2(cls2siz[ins->cls]), 0,
+ struct instr store = mkinstr(Ostore1 + ilog2(cls2siz[insrescls(*ins)]), 0,
mkref(RICON, s*8),
mkref(RREG, ins->reg-1));
addstkslotref(insertinstr(blk, ++curi, store));
@@ -335,7 +335,7 @@ regalloc(struct function *fn)
if (ins->reg-1 != ins->l.i) {
/* an in-place operation where the destination does not
* match the first operand, so we need to add a move */
- insertinstr(blk, i, mkmove(ins->cls, ins->reg-1, ins->l.i));
+ insertinstr(blk, i, mkmove(insrescls(*ins), ins->reg-1, ins->l.i));
ins->l.i = ins->reg-1;
}
}
@@ -349,7 +349,7 @@ regalloc(struct function *fn)
/* introduce necessary moves in each pred,
* XXX this doesn't work for backwards branches */
for (int i = 0; i < phi->n; ++i) {
- struct instr mov = mkinstr(Omove, ins->cls, mkref(RREG, ins->reg-1), phi->ref[i]);
+ struct instr mov = mkinstr(Omove, insrescls(*ins), mkref(RREG, ins->reg-1), phi->ref[i]);
insertinstr(phi->blk[i], phi->blk[i]->ins.n, mov);
}
}