diff options
| author | 2025-12-31 11:13:15 +0100 | |
|---|---|---|
| committer | 2025-12-31 11:13:15 +0100 | |
| commit | 97c6d5c44f30b29b52d1dc431ab9f2df4bb47fd2 (patch) | |
| tree | 564615d402793491d545d612df31dd80451120ab | |
| parent | 3a46902b3ede49116522992793d3ececef53c5a8 (diff) | |
backend: separate instrs for integer/float store
| -rw-r--r-- | aarch64/emit.c | 10 | ||||
| -rw-r--r-- | aarch64/isel.c | 29 | ||||
| -rw-r--r-- | c/c.c | 10 | ||||
| -rw-r--r-- | ir/abi0.c | 13 | ||||
| -rw-r--r-- | ir/intrin.c | 2 | ||||
| -rw-r--r-- | ir/ir.c | 5 | ||||
| -rw-r--r-- | ir/ir.h | 3 | ||||
| -rw-r--r-- | ir/mem2reg.c | 10 | ||||
| -rw-r--r-- | ir/op.def | 10 | ||||
| -rw-r--r-- | ir/regalloc.c | 6 | ||||
| -rw-r--r-- | x86_64/emit.c | 12 | ||||
| -rw-r--r-- | x86_64/isel.c | 4 | ||||
| -rw-r--r-- | x86_64/sysv.c | 14 |
13 files changed, 79 insertions, 49 deletions
diff --git a/aarch64/emit.c b/aarch64/emit.c index 2ca3af9..564ce2a 100644 --- a/aarch64/emit.c +++ b/aarch64/emit.c @@ -680,12 +680,12 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc Load: X2(pcode, cls, reg2oper(ins->reg-1), mkmemoper(8<<(ins->op - Oloads8)/2, ins->l)); break; - case Ostore8: cls = KI32; X2 = Xstrb; goto Store; - case Ostore16: cls = KI32; X2 = Xstrh; goto Store; - case Ostore32: cls = KI32; X2 = Xstr; goto Store; - case Ostore64: cls = KI64; X2 = Xstr; + case Ostorei8: cls = KI32; X2 = Xstrb; goto Store; + case Ostorei16: cls = KI32; X2 = Xstrh; goto Store; + case Ostorei32: cls = KI32; X2 = Xstr; goto Store; + case Ostorei64: cls = KI64; X2 = Xstr; Store: - X2(pcode, cls, ref2oper(ins->r), mkmemoper(8<<(ins->op-Ostore8), ins->l)); + X2(pcode, cls, ref2oper(ins->r), mkmemoper(8<<(ins->op-Ostorei8), ins->l)); break; case Ocall: Xcall(pcode, ref2oper(ins->l)); diff --git a/aarch64/isel.c b/aarch64/isel.c index 6e457d0..2e82361 100644 --- a/aarch64/isel.c +++ b/aarch64/isel.c @@ -147,7 +147,7 @@ selcall(struct function *fn, struct instr *ins, struct block *blk, int *curi) union ref adr = mkaddr((struct addr){mkref(RREG, SP), .disp = abi.stk}); int iargsave = iarg; if (!abi.ty.isagg) { /* scalar arg in stack */ - *arg = mkinstr(Ostore8+ilog2(cls2siz[abi.ty.cls]), 0, adr, arg->r); + *arg = mkinstr(cls2store[abi.ty.cls], 0, adr, arg->r); if (isaddrcon(arg->r,1) || arg->r.t == RADDR) arg->r = insertinstr(blk, iarg++, mkinstr(Ocopy, abi.ty.cls, arg->r)); else @@ -284,11 +284,26 @@ fuseaddr(union ref *r, struct block *blk, int *curi, uint siz/*1,2,4,8*/) return 1; } - +static const uchar loadsz[] = { + [Oloads8 - Oloads8] = 1, [Oloadu8 - Oloads8] = 1, + [Oloads16 - Oloads8] = 2, [Oloadu16 - Oloads8] = 2, + [Oloads32 - Oloads8] = 4, [Oloadu32 - Oloads8] = 4, + [Oloadi64 - Oloads8] = 8, + [Oloadf32 - Oloads8] = 4, + [Oloadf64 - Oloads8] = 8, +}; +static const uchar storesz[] = { + [Ostorei8 - Ostorei8] = 1, + [Ostorei16 - Ostorei8] = 2, + [Ostorei32 - Ostorei8] = 4, + [Ostorei64 - Ostorei8] = 8, + [Ostoref32 - Ostorei8] = 4, + [Ostoref64 - Ostorei8] = 8, +}; static void loadstoreaddr(struct block *blk, union ref *r, int *curi, enum op op) { - uint siz = oisload(op) ? 1<<(op - Oloads8)/2 : 1<<(op - Ostore8); + uint siz = oisload(op) ? loadsz[op] : storesz[op]; if (isimm32(*r)) { *r = mkaddr((struct addr){.base = *r}); } else if (isaddrcon(*r, 0)) { @@ -306,6 +321,7 @@ static void sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) { enum op op = ins->op; + enum irclass cls; if (oisarith(ins->op) && arithfold(ins)) { fixarg(&ins->l, ins, blk, curi); @@ -377,9 +393,12 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) case Oloads32: case Oloadu32: case Oloadi64: loadstoreaddr(blk, &ins->l, curi, op); break; - case Ostore8: case Ostore16: case Ostore32: case Ostore64: + case Ostorei8: case Ostorei16: case Ostorei32: cls = KI32; goto Store; + case Ostorei64: cls = KI64; goto Store; + case Ostoref32: cls = KF32; goto Store; + case Ostoref64: cls = KF64; Store: loadstoreaddr(blk, &ins->l, curi, op); - regarg(&ins->r, op == Ostore64 ? KI64 : KI32, blk, curi); + regarg(&ins->r, cls, blk, curi); break; } } @@ -2951,10 +2951,10 @@ genstore(struct function *fn, union type t, union ref ptr, union ref val) assert(isscalar(t)); switch (typesize(t)) { - case 1: ins.op = Ostore8; break; - case 2: ins.op = Ostore16; break; - case 4: ins.op = Ostore32; break; - case 8: ins.op = Ostore64; break; + case 1: ins.op = Ostorei8; break; + case 2: ins.op = Ostorei16; break; + case 4: ins.op = isflt(t) ? Ostoref32 : Ostorei32; break; + case 8: ins.op = isflt(t) ? Ostoref64 : Ostorei64; break; default: assert(0); } ins.l = ptr; @@ -2988,7 +2988,7 @@ geninit(struct function *fn, union type t, union ref dst, const struct expr *src /* write individual zeros at non initialized gaps */ for (uint i = 0; bsiter(&i, azero, countof(azero)) && i < siz; i += align) { adr = irbinop(fn, Oadd, KPTR, dst, mkref(RICON, i)); - addinstr(fn, mkinstr(Ostore8 + ilog2(align), 0, .l = adr, .r = ZEROREF)); + addinstr(fn, mkinstr(Ostorei8 + ilog2(align), 0, .l = adr, .r = ZEROREF)); } } else { goto Memset0; @@ -121,11 +121,11 @@ patchparam(struct function *fn, int *curi, int *param, int tydat, int nabi, stru * store* %x, %a * store* %x + N, %b */ - st = mkinstr(Ostore8 + ilog2(cls2siz[abi[0].ty.cls]), 0, alloc, r[0]); + st = mkinstr(cls2store[abi[0].ty.cls], 0, alloc, r[0]); insertinstr(blk, ++*curi, st); if (nabi > 1) { struct instr tmp = mkinstr(Oadd, KPTR, alloc, mkref(RICON, r2off)); - st = mkinstr(Ostore8 + ilog2(cls2siz[abi[1].ty.cls]), 0, insertinstr(blk, ++*curi, tmp), r[1]); + st = mkinstr(cls2store[abi[1].ty.cls], 0, insertinstr(blk, ++*curi, tmp), r[1]); insertinstr(blk, ++*curi, st); } } @@ -226,7 +226,7 @@ patcharg(struct block *blk, int *icall, struct call *call, union ref sadr = off == 0 ? src : insertinstr(blk, ++arginst, mkinstr(Oadd, KPTR, src, mkref(RICON, off))); union ref tmp = insertinstr(blk, ++arginst, mkinstr(Oloads8+2*ilog2(align), align < 8 ? KI32 : KI64, sadr)); union ref dadr = off == 0 ? dst : insertinstr(blk, ++arginst, mkinstr(Oadd, KPTR, dst, mkref(RICON, off))); - insertinstr(blk, ++arginst, mkinstr(Ostore8+ilog2(align), 0, dadr, tmp)); + insertinstr(blk, ++arginst, mkinstr(Ostorei8+ilog2(align), 0, dadr, tmp)); } *icall = arginst + (call->narg - argidx); return 1; @@ -320,12 +320,7 @@ abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi) r[1] = insertinstr(blk, ++*curi, ret2); } for (int i = 0; i < nret; ++i) { - struct instr store = {0}; - switch (call->abiret[i].ty.cls) { - default: assert(0); - case KF32: case KI32: store.op = Ostore32; break; - case KI64: case KF64: store.op = Ostore64; break; - } + struct instr store = { cls2store[call->abiret[i].ty.cls] }; if (i == 0) { store.l = retmem; } else { diff --git a/ir/intrin.c b/ir/intrin.c index dcd05a5..ca49341 100644 --- a/ir/intrin.c +++ b/ir/intrin.c @@ -37,7 +37,7 @@ intrin(struct block *blk, int *curi, enum intrin in, struct arg *args, int narg, psrc = insertinstr(blk, ++*curi, mkinstr(Oadd, KPTR, *args[1].arg, mkref(RICON, off))); } src = insertinstr(blk, ++*curi, mkinstr(Oloads8 + 2*ilog2(step), step < 8 ? KI32 : KI64, psrc)); - insertinstr(blk, ++*curi, mkinstr(Ostore8 + ilog2(step), 0, pdst, src)); + insertinstr(blk, ++*curi, mkinstr(Ostorei8 + ilog2(step), 0, pdst, src)); } return 1; } @@ -6,6 +6,9 @@ uchar cls2siz[] = { [KI32] = 4, [KI64] = 8, [KF32] = 4, [KF64] = 8 }; uchar cls2load[] = { [KI32] = Oloads32, [KI64] = Oloadi64, [KF32] = Oloadf32, [KF64] = Oloadf64, [KPTR] = -1 +}, cls2store[] = { + [KI32] = Ostorei32, [KI64] = Ostorei64, + [KF32] = Ostoref32, [KF64] = Ostoref64, [KPTR] = -1 }; const uchar siz2intcls[] = { [1] = KI32, [2] = KI32, [4] = KI32, [8] = KI64 }; @@ -71,6 +74,7 @@ irinit(struct function *fn) type2cls[TYARRAY] = KPTR; cls2siz[KPTR] = targ_primsizes[TYPTR]; cls2load[KPTR] = targ_64bit ? Oloadi64 : Oloads32; + cls2store[KPTR] = targ_64bit ? Ostorei64 : Ostorei32; } fn->entry = fn->curblk = allocz(fn->arena, sizeof(struct block), 0); fn->nblk = 1; @@ -513,6 +517,7 @@ replcuses(union ref from, union ref to) } else if (instrtab[use->u].op == Ophi) { u = phitab.p[instrtab[use->u].l.i]; n = use->blk->npred; + if (use->blk->phi.n == 0) continue; /* shouldn't happen */ } else { u = &instrtab[use->u].l; n = 2; @@ -101,7 +101,7 @@ enum op { #define oiscmp(o) in_range(o, Oequ, Ougte) #define oisarith(o) in_range(o, Oneg, Ougte) #define oisalloca(o) in_range(o, Oalloca1, Oalloca16) -#define oisstore(o) in_range(o, Ostore8, Ostore64) +#define oisstore(o) in_range(o, Ostorei8, Ostoref64) #define oisload(o) in_range(o, Oloads8, Oloadf64) extern const char *opnames[]; extern const uchar opnarg[]; @@ -235,6 +235,7 @@ enum { MAXINSTR = 1<<15 }; extern uchar type2cls[]; extern uchar cls2siz[]; extern uchar cls2load[]; +extern uchar cls2store[]; extern const uchar siz2intcls[]; extern struct instr instrtab[]; extern struct use *instruse[]; diff --git a/ir/mem2reg.c b/ir/mem2reg.c index 4b0b007..7a5874c 100644 --- a/ir/mem2reg.c +++ b/ir/mem2reg.c @@ -15,10 +15,18 @@ static const uchar load2ext[] = { [Oloads32 - Oloads8] = Oexts32, [Oloadu32 - Oloads8] = Oextu32, [Oloadi64 - Oloads8] = Ocopy, }; +static const uchar storesz[] = { + [Ostorei8 - Ostorei8] = 1, + [Ostorei16 - Ostorei8] = 2, + [Ostorei32 - Ostorei8] = 4, + [Ostorei64 - Ostorei8] = 8, + [Ostoref32 - Ostorei8] = 4, + [Ostoref64 - Ostorei8] = 8, +}; #define loadsz(o) (loadszcls[(o) - Oloads8] & 0xF) #define loadcls(o) (loadszcls[(o) - Oloads8] >> 4) #define load2ext(o) (load2ext[(o) - Oloads8]) -#define storesz(o) (1 << ((o) - Ostore8)) +#define storesz(o) (storesz[(o) - Ostorei8]) /* Implements algorithm in 'Simple and Efficient Construction of Static Single Assignment' (Braun et al) */ @@ -57,10 +57,12 @@ _(loadu32, 1) _(loadi64, 1) _(loadf32, 1) _(loadf64, 1) -_(store8, 2) -_(store16, 2) -_(store32, 2) -_(store64, 2) +_(storei8, 2) +_(storei16, 2) +_(storei32, 2) +_(storei64, 2) +_(storef32, 2) +_(storef64, 2) _(param, 2) _(arg, 2) _(call, 2) diff --git a/ir/regalloc.c b/ir/regalloc.c index 9678559..39a3f74 100644 --- a/ir/regalloc.c +++ b/ir/regalloc.c @@ -264,7 +264,7 @@ emitmove(enum irclass k, union alloc dst, union alloc src, struct block *blk, in addstkslotref(insertinstr(blk, curi++, mv).i, src.a*8); } else reg = src.a; if (dst.t == ASTACK) { - mv = mkinstr(Ostore8+ilog2(cls2siz[k]), 0, .r = mkref(RREG, reg)); + mv = mkinstr(cls2store[k], 0, .r = mkref(RREG, reg)); addstkslotref(insertinstr(blk, curi, mv).i, dst.a*8); } } @@ -1137,7 +1137,7 @@ devirt(struct rega *ra, struct block *blk) alloc = temp < ra->intervals.ntemps && (it = &ra->intervals.temps[temp]) && it->nrange ? &it->alloc : NULL; if (alloc && alloc->t == ASTACK) { enum irclass cls = insrescls(*ins); - int store = Ostore8 + ilog2(cls2siz[cls]); + int store = cls2store[cls]; /* t was spilled, gen store */ if (ins->op == Ocopy && ins->l.t != RADDR) { ins->op = store; @@ -1171,7 +1171,7 @@ devirt(struct rega *ra, struct block *blk) } } } - if (!ins->reg && insrescls(*ins) && ins->op != Omove && !ins->keep && !in_range(ins->op, Ostore8, Ostore64)) { + if (!ins->reg && insrescls(*ins) && ins->op != Omove && !ins->keep && !oisstore(ins->op)) { /* dead */ Nop: ins->op = Onop; diff --git a/x86_64/emit.c b/x86_64/emit.c index b0b4f58..783ea20 100644 --- a/x86_64/emit.c +++ b/x86_64/emit.c @@ -979,14 +979,14 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc dst = reg2oper(ins->reg-1); gencopy(pcode, cls, blk, curi, dst, ins->l); break; - case Ostore8: cls = KI32, X = Xmovb; goto Store; - case Ostore16: cls = KI32, X = Xmovw; goto Store; - case Ostore32: cls = KI32, X = Xmov; goto Store; - case Ostore64: cls = KI64, X = Xmov; + case Ostorei8: cls = KI32, X = Xmovb; goto Store; + case Ostorei16: cls = KI32, X = Xmovw; goto Store; + case Ostorei32: cls = KI32, X = Xmov; goto Store; + case Ostorei64: cls = KI64, X = Xmov; goto Store; + case Ostoref32: cls = KF32, X = Xmov; goto Store; + case Ostoref64: cls = KF64, X = Xmov; goto Store; Store: src = mkimmregoper(ins->r); - if (cls == KI32 && src.t == OREG && src.reg >= XMM0) cls = KF32; - if (cls == KI64 && src.t == OREG && src.reg >= XMM0) cls = KF64; X(pcode, cls, mkmemoper(ins->l), src); break; case Oexts8: src = mkregoper(ins->l); goto Movsxb; diff --git a/x86_64/isel.c b/x86_64/isel.c index d69f9ad..8a845ef 100644 --- a/x86_64/isel.c +++ b/x86_64/isel.c @@ -139,7 +139,7 @@ selcall(struct function *fn, struct instr *ins, struct block *blk, int *curi) union ref adr = mkaddr((struct addr){mkref(RREG, RSP), .disp = abi.stk}); int iargsave = iarg; if (!abi.ty.isagg) { /* scalar arg in stack */ - *arg = mkinstr(Ostore8+ilog2(cls2siz[abi.ty.cls]), 0, adr, arg->r); + *arg = mkinstr(cls2store[abi.ty.cls], 0, adr, arg->r); if (isaddrcon(arg->r,1) || arg->r.t == RADDR) arg->r = insertinstr(blk, iarg++, mkinstr(Ocopy, abi.ty.cls, arg->r)); else @@ -497,7 +497,7 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) case Oloads32: case Oloadu32: case Oloadi64: case Oloadf32: case Oloadf64: loadstoreaddr(blk, &ins->l, curi); break; - case Ostore8: case Ostore16: case Ostore32: case Ostore64: + case Ostorei8: case Ostorei16: case Ostorei32: case Ostorei64: case Ostoref32: case Ostoref64: loadstoreaddr(blk, &ins->l, curi); if (isaddrcon(ins->r,1) || ins->r.t == RADDR) ins->r = insertinstr(blk, (*curi)++, mkinstr(Ocopy, KPTR, ins->r)); diff --git a/x86_64/sysv.c b/x86_64/sysv.c index 6313b07..317f40f 100644 --- a/x86_64/sysv.c +++ b/x86_64/sysv.c @@ -195,16 +195,16 @@ vastart(struct function *fn, struct block *blk, int *curi) *ins = mkinstr(Oadd, KPTR, ap, mkref(RICON, 16)); dst = mkref(RTMP, ins - instrtab); int i = *curi + 1; - insertinstr(blk, i++, mkinstr(Ostore64, 0, dst, rsave)); + insertinstr(blk, i++, mkinstr(Ostorei64, 0, dst, rsave)); /* set ap->overflow_arg_area */ src = insertinstr(blk, i++, mkinstr(Oadd, KPTR, mkref(RREG, RBP), mkref(RICON, 16+stk0))); dst = insertinstr(blk, i++, mkinstr(Oadd, KPTR, ap, mkref(RICON, 8))); - insertinstr(blk, i++, mkinstr(Ostore64, 0, dst, src)); + insertinstr(blk, i++, mkinstr(Ostorei64, 0, dst, src)); /* set ap->gp_offset */ - insertinstr(blk, i++, mkinstr(Ostore32, 0, ap, mkref(RICON, gpr0*8))); + insertinstr(blk, i++, mkinstr(Ostorei32, 0, ap, mkref(RICON, gpr0*8))); /* set ap->fp_offset */ dst = insertinstr(blk, i++, mkinstr(Oadd, KPTR, ap, mkref(RICON, 4))); - insertinstr(blk, i++, mkinstr(Ostore32, 0, dst, mkref(RICON, 6*8 + fpr0*16))); + insertinstr(blk, i++, mkinstr(Ostorei32, 0, dst, mkref(RICON, 6*8 + fpr0*16))); *curi = i-1; } @@ -246,7 +246,7 @@ vaarg(struct function *fn, struct block *blk, int *curi) phiargs[0] = irbinop(fn, Oadd, KPTR, sav, roff); /* l->gp/fp_offset += num_gp/fp * 8(16) */ roff = irbinop(fn, Oadd, KI32, roff, mkref(RICON, ni ? ni * 8 : nf * 16)); - addinstr(fn, mkinstr(Ostore32, 0, irbinop(fn, Oadd, KPTR, ap, mkref(RICON, ni ? 0 : 4)), roff)); + addinstr(fn, mkinstr(Ostorei32, 0, irbinop(fn, Oadd, KPTR, ap, mkref(RICON, ni ? 0 : 4)), roff)); assert(merge->npred == 1); blkpred(merge, 0) = blk->s1; blk->s1->jmp.t = Jb; @@ -262,7 +262,7 @@ vaarg(struct function *fn, struct block *blk, int *curi) phiargs[1] = ovf; /* update l->overflow_arg_area += size */ int siz = 8; - addinstr(fn, mkinstr(Ostore64, 0, adr, irbinop(fn, Oadd, KPTR, ovf, mkref(RICON, siz)))); + addinstr(fn, mkinstr(Ostorei64, 0, adr, irbinop(fn, Oadd, KPTR, ovf, mkref(RICON, siz)))); putbranch(fn, merge); } assert(merge->npred == 2); @@ -276,7 +276,7 @@ vaarg(struct function *fn, struct block *blk, int *curi) } else { instrtab[var] = mkalloca(8, 8); tmp = insertinstr(merge, 1, mkinstr(Oloadi64, KI64, phi)); - insertinstr(merge, 2, mkinstr(Ostore64, 0, mkref(RTMP, var), tmp)); + insertinstr(merge, 2, mkinstr(Ostorei64, 0, mkref(RTMP, var), tmp)); } fn->prop &= ~FNUSE; } else { |