From 2cdf90f0683e4da3afc8554d17859260fdc6b4dc Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 23 Apr 2013 00:08:04 +0200 Subject: [PATCH] Always emit TOSTR for non-string CAT operands. Fuse in backend. --- src/lj_asm.c | 30 +++++++++++++++++------------- src/lj_opt_fold.c | 28 ++++++++++++---------------- src/lj_record.c | 9 ++++++--- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/lj_asm.c b/src/lj_asm.c index 7ebde7b8..a550d3b3 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -1057,26 +1057,30 @@ static void asm_bufhdr(ASMState *as, IRIns *ir) static void asm_bufput(ASMState *as, IRIns *ir) { - const CCallInfo *ci; + const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_buf_putstr]; IRRef args[2]; - IRIns *ir2; + IRIns *irs; if (!ra_used(ir)) return; args[0] = ir->op1; /* SBuf * */ - args[1] = ir->op2; /* int, double, GCstr * */ - ir2 = IR(ir->op2); - if (irt_isstr(ir2->t)) { - ci = &lj_ir_callinfo[IRCALL_lj_buf_putstr]; - } else if (LJ_SOFTFP ? irt_type((ir2+1)->t)==IRT_SOFTFP : irt_isnum(ir2->t)) { - ci = &lj_ir_callinfo[IRCALL_lj_buf_putnum]; - args[1] = ASMREF_TMP1; - } else { - lua_assert(irt_isinteger(ir2->t)); - ci = &lj_ir_callinfo[IRCALL_lj_buf_putint]; + 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_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]; + args[1] = ASMREF_TMP1; /* TValue * */ + } else { + lua_assert(irt_isinteger(IR(irs->op1)->t)); + ci = &lj_ir_callinfo[IRCALL_lj_buf_putint]; + args[1] = irs->op1; /* int */ + } + } } asm_setupresult(as, ir, ci); /* SBuf * */ asm_gencall(as, ci, args); if (args[1] == ASMREF_TMP1) - asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2); + asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), irs->op1); } static void asm_bufstr(ASMState *as, IRIns *ir) diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index fc91a75e..e3194f76 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c @@ -541,13 +541,13 @@ LJFOLDF(bufput_append) LJFOLD(BUFPUT any any) LJFOLDF(bufput_kgc) { - if (fright->o == IR_KGC) { + if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD) && fright->o == IR_KGC) { GCstr *s2 = ir_kstr(fright); MSize len2 = s2->len; if (len2 == 0) { /* Empty string? */ return LEFTFOLD; } else { - if (fleft->o == IR_BUFPUT && IR(fleft->op2)->o == IR_KGC && + if (fleft->o == IR_BUFPUT && irref_isk(fleft->op2) && !irt_isphi(fleft->t)) { /* Join two constant string puts in a row. */ GCstr *s1 = ir_kstr(IR(fleft->op2)); @@ -570,20 +570,16 @@ LJFOLD(BUFSTR any any) LJFOLDF(bufstr_kfold_cse) { lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT); - if (fright->o == IR_BUFHDR) { /* No put operations? */ - if (!(fright->op2 & IRBUFHDR_APPEND)) /* Empty buffer? */ - return lj_ir_kstr(J, &J2G(J)->strempty); - fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ - return CSEFOLD; - } else { - /* Shortcut for a single put operation. */ - IRIns *irb = IR(fright->op1); - if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) { - IRRef ref = fright->op2; - if (irt_isstr(IR(ref)->t)) - return ref; - lua_assert(irt_isinteger(IR(ref)->t) || irt_isnum(IR(ref)->t)); - return emitir(IRT(IR_TOSTR, IRT_STR), ref, 0); + if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) { + if (fright->o == IR_BUFHDR) { /* No put operations? */ + if (!(fright->op2 & IRBUFHDR_APPEND)) /* Empty buffer? */ + return lj_ir_kstr(J, &J2G(J)->strempty); + fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ + return CSEFOLD; + } else { + IRIns *irb = IR(fright->op1); + if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) + return fright->op2; /* Shortcut for a single put operation. */ } } /* Try to CSE the whole chain. */ diff --git a/src/lj_record.c b/src/lj_record.c index bbabd3ce..bafb6ff7 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -1608,10 +1608,13 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) lua_assert(baseslot < topslot); if (tref_isnumber_str(tr) && tref_isnumber_str(*(top-1))) { TRef hdr, *trp, *xbase, *base = &J->base[baseslot]; - /* First convert number consts to string consts to simplify FOLD rules. */ - for (trp = top; trp >= base && tref_isnumber_str(*trp); trp--) - if (tref_isk(*trp) && tref_isnumber(*trp)) + /* First convert numbers to strings. */ + for (trp = top; trp >= base; trp--) { + if (tref_isnumber(*trp)) *trp = emitir(IRT(IR_TOSTR, IRT_STR), *trp, 0); + else if (!tref_isstr(*trp)) + break; + } xbase = ++trp; tr = hdr = emitir(IRT(IR_BUFHDR, IRT_P32), lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET);