diff options
author | Mike Pall <mike> | 2013-04-23 00:56:03 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2013-04-23 00:56:03 +0200 |
commit | 557391c3b7110cdb431a26351e87010e7f1a41e9 (patch) | |
tree | 0e436f0d5fa052097adc38ba4af9ffa624a9766a | |
parent | 2cdf90f0683e4da3afc8554d17859260fdc6b4dc (diff) | |
download | luajit-557391c3b7110cdb431a26351e87010e7f1a41e9.tar.gz luajit-557391c3b7110cdb431a26351e87010e7f1a41e9.tar.bz2 luajit-557391c3b7110cdb431a26351e87010e7f1a41e9.zip |
Fuse string creation into concats. Optimize single-char concats.
-rw-r--r-- | src/lj_asm.c | 29 | ||||
-rw-r--r-- | src/lj_buf.c | 11 | ||||
-rw-r--r-- | src/lj_buf.h | 3 | ||||
-rw-r--r-- | 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) | |||
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; |
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) | |||
58 | return p; | 58 | return p; |
59 | } | 59 | } |
60 | 60 | ||
61 | void lj_buf_putmem(SBuf *sb, const void *q, MSize len) | 61 | SBuf * lj_buf_putmem(SBuf *sb, const void *q, MSize len) |
62 | { | 62 | { |
63 | char *p = lj_buf_more(sb, len); | 63 | char *p = lj_buf_more(sb, len); |
64 | p = lj_buf_wmem(p, q, len); | 64 | p = lj_buf_wmem(p, q, len); |
65 | setsbufP(sb, p); | 65 | setsbufP(sb, p); |
66 | return sb; | ||
66 | } | 67 | } |
67 | 68 | ||
68 | #if LJ_HASJIT | 69 | #if LJ_HASJIT |
@@ -75,6 +76,14 @@ SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s) | |||
75 | return sb; | 76 | return sb; |
76 | } | 77 | } |
77 | 78 | ||
79 | SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c) | ||
80 | { | ||
81 | char *p = lj_buf_more(sb, 1); | ||
82 | *p++ = (char)c; | ||
83 | setsbufP(sb, p); | ||
84 | return sb; | ||
85 | } | ||
86 | |||
78 | SBuf * LJ_FASTCALL lj_buf_putint(SBuf *sb, int32_t k) | 87 | SBuf * LJ_FASTCALL lj_buf_putint(SBuf *sb, int32_t k) |
79 | { | 88 | { |
80 | setsbufP(sb, lj_str_bufint(lj_buf_more(sb, LJ_STR_INTBUF), k)); | 89 | 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); | |||
25 | LJ_FUNC void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb); | 25 | LJ_FUNC void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb); |
26 | 26 | ||
27 | LJ_FUNC char *lj_buf_wmem(char *p, const void *q, MSize len); | 27 | LJ_FUNC char *lj_buf_wmem(char *p, const void *q, MSize len); |
28 | LJ_FUNC void lj_buf_putmem(SBuf *sb, const void *q, MSize len); | 28 | LJ_FUNC SBuf * lj_buf_putmem(SBuf *sb, const void *q, MSize len); |
29 | #if LJ_HASJIT | 29 | #if LJ_HASJIT |
30 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s); | 30 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s); |
31 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); | ||
31 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putint(SBuf *sb, int32_t k); | 32 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putint(SBuf *sb, int32_t k); |
32 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putnum(SBuf *sb, cTValue *o); | 33 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putnum(SBuf *sb, cTValue *o); |
33 | LJ_FUNC GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb); | 34 | 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 { | |||
105 | _(ANY, lj_strscan_num, 2, FN, INT, 0) \ | 105 | _(ANY, lj_strscan_num, 2, FN, INT, 0) \ |
106 | _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ | 106 | _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ |
107 | _(ANY, lj_str_fromnum, 2, FN, STR, CCI_L) \ | 107 | _(ANY, lj_str_fromnum, 2, FN, STR, CCI_L) \ |
108 | _(ANY, lj_buf_putmem, 3, S, P32, 0) \ | ||
108 | _(ANY, lj_buf_putstr, 2, FS, P32, 0) \ | 109 | _(ANY, lj_buf_putstr, 2, FS, P32, 0) \ |
110 | _(ANY, lj_buf_putchar, 2, FS, P32, 0) \ | ||
109 | _(ANY, lj_buf_putint, 2, FS, P32, 0) \ | 111 | _(ANY, lj_buf_putint, 2, FS, P32, 0) \ |
110 | _(ANY, lj_buf_putnum, 2, FS, P32, 0) \ | 112 | _(ANY, lj_buf_putnum, 2, FS, P32, 0) \ |
111 | _(ANY, lj_buf_tostr, 1, FL, STR, 0) \ | 113 | _(ANY, lj_buf_tostr, 1, FL, STR, 0) \ |