diff options
| author | 2023-06-12 19:16:39 +0200 | |
|---|---|---|
| committer | 2023-06-12 19:16:39 +0200 | |
| commit | 106fe60243bd61d017d28795f6eba68fecc981b4 (patch) | |
| tree | 7fbb5c1a84346af8243630cb6c0057ab9b475978 | |
| parent | 6df4f80c99609162ad3e46bfdce46d0c10696a45 (diff) | |
dec,inc,sub
| -rw-r--r-- | amd64/emit.c | 22 | ||||
| -rw-r--r-- | amd64/isel.c | 18 | ||||
| -rw-r--r-- | op.def | 3 | ||||
| -rw-r--r-- | regalloc.c | 1 | ||||
| -rw-r--r-- | test/test3.c | 16 |
5 files changed, 57 insertions, 3 deletions
diff --git a/amd64/emit.c b/amd64/emit.c index a89b021..e1d9463 100644 --- a/amd64/emit.c +++ b/amd64/emit.c @@ -280,11 +280,24 @@ DEFINSTR2(Xadd, {4, PFPR, PMEM, "\xF3\x0F\x58", EN_RM}, /* ADDSS xmm, m32 */ {8, PFPR, PMEM, "\xF2\x0F\x58", EN_RM}, /* ADDSD xmm, m64 */ ) +DEFINSTR2(Xsub, + {4|8, PGPR, PGPR, "\x2B", EN_RR}, /* SUB r32/64, r32/64 */ + {4|8, PGPR, PI8, "\x83", EN_RI8, .ext=5}, /* SUB r32/64, imm8 */ + {4|8, PRAX, PI32, "\x2D", EN_I32}, /* SUB eax/rax, imm */ + {4|8, PGPR, PI32, "\x81", EN_RI32, .ext=5}, /* SUB r32/64, imm */ + { 8, PGPR, PMEM, "\x2B", EN_RM}, /* SUB r64, m64 */ + {4, PFPR, PFPR, "\xF3\x0F\x5C", EN_RR}, /* SUBSS xmm, xmm */ + {8, PFPR, PFPR, "\xF2\x0F\x5C", EN_RR}, /* SUBSD xmm, xmm */ + {4, PFPR, PMEM, "\xF3\x0F\x5C", EN_RM}, /* SUBSS xmm, m32 */ + {8, PFPR, PMEM, "\xF2\x0F\x5C", EN_RM}, /* SUBSD xmm, m64 */ +) DEFINSTR2(Xshl, {4|8, PGPR, P1, "\xD1", EN_R, .ext=4}, /* SHL r32/64, 1 */ {4|8, PGPR, PI32, "\xC1", EN_RI8, .ext=4}, /* SHL r32/64, imm */ {4|8, PGPR, PRCX, "\xD3", EN_R, .ext=4}, /* SHL r32/64, CL */ ) +DEFINSTR1(Xinc, {4|8, PGPR, 0, "\xFF", EN_R, .ext=0} /* INC r32/64 */) +DEFINSTR1(Xdec, {4|8, PGPR, 0, "\xFF", EN_R, .ext=1} /* DEC r32/64 */) DEFINSTR1(Xidiv, {4|8, PGPR, 0, "\xF7", EN_R, .ext=7}, /* IDIV r32/64 */ {4|8, PMEM, 0, "\xF7", EN_M, .ext=7}, /* IDIV m32/64 */ @@ -433,6 +446,7 @@ emitinstr(uchar **pcode, uint *stktop, struct function *fn, struct block *blk, i struct oper dst, src; uchar ksiz = cls2siz[ins->cls]; void (*X)(uchar **, uint, struct oper, struct oper) = NULL; + void (*X1)(uchar **, uint, struct oper) = NULL; if (oisalloca(ins->op)) { uint alignlog2 = ins->op - Oalloca1; @@ -473,12 +487,20 @@ emitinstr(uchar **pcode, uint *stktop, struct function *fn, struct block *blk, i Xlea(pcode, ksiz, dst, mem); } break; + case Osub: X = Xsub; goto ALU2; case Oshl: X = Xshl; goto ALU2; ALU2: dst = mkregoper(ins->l); assert(ins->reg-1 == dst.reg); X(pcode, ksiz, dst, mkimmdatregoper(ins->r)); break; + case Oxinc: X1 = Xinc; goto ALU1; + case Oxdec: X1 = Xdec; goto ALU1; + ALU1: + dst = mkregoper(ins->l); + assert(ins->reg-1 == dst.reg); + X1(pcode, ksiz, dst); + break; case Odiv: case Orem: switch (ins->cls) { case KI8: B(0x48); /* REX.W */ diff --git a/amd64/isel.c b/amd64/isel.c index 8ab11a7..30ad222 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -171,7 +171,11 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) insertinstr(blk, ++(*curi), temp); break; case Osub: - if (iscon(ins->l)) { + if (ins->r.bits == mkref(RICON, 1).bits) { + /* sub x,1 -> dec x */ + ins->op = Oxdec; + ins->r = NOREF; + } else if (iscon(ins->l)) { /* sub imm, x -> sub x, imm; neg x */ struct instr sub = *ins; rswap(sub.l, sub.r); @@ -181,6 +185,18 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) } goto ALU; case Oadd: + if (ins->l.bits == mkref(RICON, 1).bits) { + /* add 1,x -> inc x */ + ins->op = Oxinc; + ins->l = ins->r; + ins->r = NOREF; + goto ALU; + } else if (ins->r.bits == mkref(RICON, 1).bits) { + /* add x,1 -> inc x */ + ins->op = Oxinc; + ins->r = NOREF; + goto ALU; + } if (kisint(ins->cls) && (addarg4addrp(ins->l) || addarg4addrp(ins->r))) { temp.op = Ocopy; temp.cls = ins->cls; @@ -67,3 +67,6 @@ _(arg, 2) _(call, 2) _(intrin, 2) _(phi, 1) +/* machine-specific instructions */ +_(xinc, 1) +_(xdec, 1) @@ -219,6 +219,7 @@ regalloc(struct function *fn) /* 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)); + ins->l.i = ins->reg-1; } } } diff --git a/test/test3.c b/test/test3.c index c39d15b..8bd9020 100644 --- a/test/test3.c +++ b/test/test3.c @@ -12,10 +12,22 @@ int shcl(int a, int b) { return a << (b+1); } -int div(int a,int b) { - return a < 0 ? a / b : b / a; +struct p { long x,y; }; +struct p divsh(int a) { + struct p p; + p.x = a << (a / 5); + p.y = a; + return p; } +struct bitset { unsigned long long u; }; +static inline void +bscopy(struct bitset dst[/*siz*/], const struct bitset src[/*siz*/], unsigned siz) +{ + while (siz--) dst++->u = src++->u; +} + + #if 0 long test(long x) { return x + (long)"abc"; |