diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 29 |
1 files changed, 23 insertions, 6 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) | |||
1058 | static void asm_bufput(ASMState *as, IRIns *ir) | 1058 | static void asm_bufput(ASMState *as, IRIns *ir) |
1059 | { | 1059 | { |
1060 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_buf_putstr]; | 1060 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_buf_putstr]; |
1061 | IRRef args[2]; | 1061 | IRRef args[3]; |
1062 | IRIns *irs; | 1062 | IRIns *irs; |
1063 | int kchar = -1; | ||
1063 | if (!ra_used(ir)) return; | 1064 | if (!ra_used(ir)) return; |
1064 | args[0] = ir->op1; /* SBuf * */ | 1065 | args[0] = ir->op1; /* SBuf * */ |
1065 | args[1] = ir->op2; /* GCstr * */ | 1066 | args[1] = ir->op2; /* GCstr * */ |
1066 | irs = IR(ir->op2); | 1067 | irs = IR(ir->op2); |
1067 | lua_assert(irt_isstr(irs->t)); | 1068 | lua_assert(irt_isstr(irs->t)); |
1068 | if (mayfuse(as, ir->op2) && ra_noreg(irs->r)) { | 1069 | if (irs->o == IR_KGC) { |
1070 | GCstr *s = ir_kstr(irs); | ||
1071 | if (s->len == 1) { /* Optimize put of single-char string constant. */ | ||
1072 | kchar = strdata(s)[0]; | ||
1073 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar]; | ||
1074 | args[1] = ASMREF_TMP1; /* int, truncated to char */ | ||
1075 | } | ||
1076 | } else if (mayfuse(as, ir->op2) && ra_noreg(irs->r)) { | ||
1069 | if (irs->o == IR_TOSTR) { /* Fuse number to string conversions. */ | 1077 | if (irs->o == IR_TOSTR) { /* Fuse number to string conversions. */ |
1070 | if (LJ_SOFTFP ? (irs+1)->o == IR_HIOP : irt_isnum(IR(irs->op1)->t)) { | 1078 | if (LJ_SOFTFP ? (irs+1)->o == IR_HIOP : irt_isnum(IR(irs->op1)->t)) { |
1071 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putnum]; | 1079 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putnum]; |
@@ -1075,12 +1083,21 @@ static void asm_bufput(ASMState *as, IRIns *ir) | |||
1075 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putint]; | 1083 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putint]; |
1076 | args[1] = irs->op1; /* int */ | 1084 | args[1] = irs->op1; /* int */ |
1077 | } | 1085 | } |
1086 | } else if (irs->o == IR_SNEW) { /* Fuse string allocation. */ | ||
1087 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putmem]; | ||
1088 | args[1] = irs->op1; /* const void * */ | ||
1089 | args[2] = irs->op2; /* MSize */ | ||
1078 | } | 1090 | } |
1079 | } | 1091 | } |
1080 | asm_setupresult(as, ir, ci); /* SBuf * */ | 1092 | asm_setupresult(as, ir, ci); /* SBuf * */ |
1081 | asm_gencall(as, ci, args); | 1093 | asm_gencall(as, ci, args); |
1082 | if (args[1] == ASMREF_TMP1) | 1094 | if (args[1] == ASMREF_TMP1) { |
1083 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), irs->op1); | 1095 | Reg tmp = ra_releasetmp(as, ASMREF_TMP1); |
1096 | if (kchar == -1) | ||
1097 | asm_tvptr(as, tmp, irs->op1); | ||
1098 | else | ||
1099 | ra_allockreg(as, kchar, tmp); | ||
1100 | } | ||
1084 | } | 1101 | } |
1085 | 1102 | ||
1086 | static void asm_bufstr(ASMState *as, IRIns *ir) | 1103 | static void asm_bufstr(ASMState *as, IRIns *ir) |
@@ -2015,11 +2032,11 @@ static void asm_setup_regsp(ASMState *as) | |||
2015 | /* fallthrough */ | 2032 | /* fallthrough */ |
2016 | #endif | 2033 | #endif |
2017 | /* C calls evict all scratch regs and return results in RID_RET. */ | 2034 | /* C calls evict all scratch regs and return results in RID_RET. */ |
2018 | case IR_SNEW: case IR_XSNEW: case IR_NEWREF: | 2035 | case IR_SNEW: case IR_XSNEW: case IR_NEWREF: case IR_BUFPUT: |
2019 | if (REGARG_NUMGPR < 3 && as->evenspill < 3) | 2036 | if (REGARG_NUMGPR < 3 && as->evenspill < 3) |
2020 | as->evenspill = 3; /* lj_str_new and lj_tab_newkey need 3 args. */ | 2037 | as->evenspill = 3; /* lj_str_new and lj_tab_newkey need 3 args. */ |
2021 | case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR: | 2038 | case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR: |
2022 | case IR_BUFPUT: case IR_BUFSTR: | 2039 | case IR_BUFSTR: |
2023 | ir->prev = REGSP_HINT(RID_RET); | 2040 | ir->prev = REGSP_HINT(RID_RET); |
2024 | if (inloop) | 2041 | if (inloop) |
2025 | as->modset = RSET_SCRATCH; | 2042 | as->modset = RSET_SCRATCH; |