From 557391c3b7110cdb431a26351e87010e7f1a41e9 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 23 Apr 2013 00:56:03 +0200 Subject: [PATCH] Fuse string creation into concats. Optimize single-char concats. --- src/lj_asm.c | 29 +++++++++++++++++++++++------ src/lj_buf.c | 11 ++++++++++- src/lj_buf.h | 3 ++- src/lj_ircall.h | 2 ++ 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/lj_asm.c b/src/lj_asm.c index a550d3b3..e847b8c9 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -1058,14 +1058,22 @@ static void asm_bufhdr(ASMState *as, IRIns *ir) static void asm_bufput(ASMState *as, IRIns *ir) { const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_buf_putstr]; - IRRef args[2]; + IRRef args[3]; IRIns *irs; + int kchar = -1; if (!ra_used(ir)) return; args[0] = ir->op1; /* SBuf * */ args[1] = ir->op2; /* GCstr * */ irs = IR(ir->op2); lua_assert(irt_isstr(irs->t)); - if (mayfuse(as, ir->op2) && ra_noreg(irs->r)) { + if (irs->o == IR_KGC) { + GCstr *s = ir_kstr(irs); + if (s->len == 1) { /* Optimize put of single-char string constant. */ + kchar = strdata(s)[0]; + ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar]; + args[1] = ASMREF_TMP1; /* int, truncated to char */ + } + } else if (mayfuse(as, ir->op2) && ra_noreg(irs->r)) { if (irs->o == IR_TOSTR) { /* Fuse number to string conversions. */ if (LJ_SOFTFP ? (irs+1)->o == IR_HIOP : irt_isnum(IR(irs->op1)->t)) { ci = &lj_ir_callinfo[IRCALL_lj_buf_putnum]; @@ -1075,12 +1083,21 @@ static void asm_bufput(ASMState *as, IRIns *ir) ci = &lj_ir_callinfo[IRCALL_lj_buf_putint]; args[1] = irs->op1; /* int */ } + } else if (irs->o == IR_SNEW) { /* Fuse string allocation. */ + ci = &lj_ir_callinfo[IRCALL_lj_buf_putmem]; + args[1] = irs->op1; /* const void * */ + args[2] = irs->op2; /* MSize */ } } asm_setupresult(as, ir, ci); /* SBuf * */ asm_gencall(as, ci, args); - if (args[1] == ASMREF_TMP1) - asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), irs->op1); + if (args[1] == ASMREF_TMP1) { + Reg tmp = ra_releasetmp(as, ASMREF_TMP1); + if (kchar == -1) + asm_tvptr(as, tmp, irs->op1); + else + ra_allockreg(as, kchar, tmp); + } } static void asm_bufstr(ASMState *as, IRIns *ir) @@ -2015,11 +2032,11 @@ static void asm_setup_regsp(ASMState *as) /* fallthrough */ #endif /* C calls evict all scratch regs and return results in RID_RET. */ - case IR_SNEW: case IR_XSNEW: case IR_NEWREF: + case IR_SNEW: case IR_XSNEW: case IR_NEWREF: case IR_BUFPUT: if (REGARG_NUMGPR < 3 && as->evenspill < 3) as->evenspill = 3; /* lj_str_new and lj_tab_newkey need 3 args. */ case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR: - case IR_BUFPUT: case IR_BUFSTR: + case IR_BUFSTR: ir->prev = REGSP_HINT(RID_RET); if (inloop) as->modset = RSET_SCRATCH; diff --git a/src/lj_buf.c b/src/lj_buf.c index ef48b580..67525694 100644 --- a/src/lj_buf.c +++ b/src/lj_buf.c @@ -58,11 +58,12 @@ char *lj_buf_wmem(char *p, const void *q, MSize len) return p; } -void lj_buf_putmem(SBuf *sb, const void *q, MSize len) +SBuf * lj_buf_putmem(SBuf *sb, const void *q, MSize len) { char *p = lj_buf_more(sb, len); p = lj_buf_wmem(p, q, len); setsbufP(sb, p); + return sb; } #if LJ_HASJIT @@ -75,6 +76,14 @@ SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s) return sb; } +SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c) +{ + char *p = lj_buf_more(sb, 1); + *p++ = (char)c; + setsbufP(sb, p); + return sb; +} + SBuf * LJ_FASTCALL lj_buf_putint(SBuf *sb, int32_t k) { setsbufP(sb, lj_str_bufint(lj_buf_more(sb, LJ_STR_INTBUF), k)); diff --git a/src/lj_buf.h b/src/lj_buf.h index e028a434..426ec720 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h @@ -25,9 +25,10 @@ LJ_FUNC void LJ_FASTCALL lj_buf_grow(SBuf *sb, char *en); LJ_FUNC void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb); LJ_FUNC char *lj_buf_wmem(char *p, const void *q, MSize len); -LJ_FUNC void lj_buf_putmem(SBuf *sb, const void *q, MSize len); +LJ_FUNC SBuf * lj_buf_putmem(SBuf *sb, const void *q, MSize len); #if LJ_HASJIT LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s); +LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putint(SBuf *sb, int32_t k); LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putnum(SBuf *sb, cTValue *o); LJ_FUNC GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb); diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 3b1cc928..46bb54fe 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h @@ -105,7 +105,9 @@ typedef struct CCallInfo { _(ANY, lj_strscan_num, 2, FN, INT, 0) \ _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ _(ANY, lj_str_fromnum, 2, FN, STR, CCI_L) \ + _(ANY, lj_buf_putmem, 3, S, P32, 0) \ _(ANY, lj_buf_putstr, 2, FS, P32, 0) \ + _(ANY, lj_buf_putchar, 2, FS, P32, 0) \ _(ANY, lj_buf_putint, 2, FS, P32, 0) \ _(ANY, lj_buf_putnum, 2, FS, P32, 0) \ _(ANY, lj_buf_tostr, 1, FL, STR, 0) \