diff options
| author | 2025-12-20 07:54:46 +0100 | |
|---|---|---|
| committer | 2025-12-20 10:31:27 +0100 | |
| commit | f7167c9ec81a0e8cd99f6692fa60ae1d476c9758 (patch) | |
| tree | 6819df34361e1cb4efeb6ab448204b89b39fba6e | |
| parent | 0b62a35ad498885bfbeba273ccc132ae8f776789 (diff) | |
x86-64: peephole optimization for 3-address shift -> lea
| -rw-r--r-- | x86_64/emit.c | 15 | ||||
| -rw-r--r-- | x86_64/isel.c | 1 |
2 files changed, 15 insertions, 1 deletions
diff --git a/x86_64/emit.c b/x86_64/emit.c index f5b63fa..77f421e 100644 --- a/x86_64/emit.c +++ b/x86_64/emit.c @@ -1044,7 +1044,20 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc mkoper(OMEM, .base = mkregoper(ins->l).reg, .index = NOINDEX, .disp = -intconval(ins->r))); } break; - case Oshl: X = Xshl; goto ALU2; + case Oshl: + dst = reg2oper(ins->reg-1); + src = mkregoper(ins->l); + if (dst.reg == src.reg) + Xshl(pcode, cls, dst, mkimmdatregoper(ins->r)); + else { + uint sh = ins->r.i; + assert(ins->r.t == RICON && sh <= 3); + if (sh == 1) /* shl x, 1 -> lea [x + x] */ + Xlea(pcode, cls, dst, mkoper(OMEM, .base = src.reg, .index = src.reg)); + else /* shl x, n -> lea [x*(1<<n)+0x0] */ + Xlea(pcode, cls, dst, mkoper(OMEM, .base = NOBASE, .index = src.reg, .shift = sh)); + } + break; case Osar: X = Xsar; goto ALU2; case Oslr: X = Xshr; goto ALU2; case Oand: diff --git a/x86_64/isel.c b/x86_64/isel.c index 19692ed..2b087cd 100644 --- a/x86_64/isel.c +++ b/x86_64/isel.c @@ -507,6 +507,7 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi) ALU: if (!(op == Oadd && kisint(ins->cls))) /* 3-address add is lea */ if (!(op == Omul && kisint(ins->cls) && isimm32(ins->r))) /* for (I)MUL r,r/m,imm */ + if (!(op == Oshl && ins->r.t == RICON && ins->r.i <= 3)) /* can be lea */ ins->inplace = 1; if (iscon(ins->l)) { fixarg(&ins->l, ins, blk, curi); |