History

Optimize small structure copying on x86_64

Ziyao committed 4 years ago

Commit 3715f1d1 parent fe7ee115 files · +98 −2Browse files

Unified · Split

5 files
  1. lib/bcheck.c +12 −0
  2. tcc.h +2 −0
  3. tccgen.c +33 −2
  4. tcctok.h +1 −0
  5. x86_64-gen.c +50 −0
lib/bcheck.c+12−0
@@ -292,6 +292,7 @@ DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n); · 291 unmodified lines
292292 DLL_EXPORT char *__bound_strcat(char *dest, const char *src);
293293 DLL_EXPORT char *__bound_strchr(const char *string, int ch);
294294 DLL_EXPORT char *__bound_strdup(const char *s);
295+DLL_EXPORT void __bound_struct_copy(void *dst,void *src,size_t size);
295296
296297 #if defined(__arm__) && defined(__ARM_EABI__)
297298 DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size);
@@ -424,6 +425,7 @@ static unsigned long long bound_strncmp_count; · 126 unmodified lines
424425 static unsigned long long bound_strcat_count;
425426 static unsigned long long bound_strchr_count;
426427 static unsigned long long bound_strdup_count;
428+static unsigned long long bound_struct_copy_count;
427429 static unsigned long long bound_not_found;
428430 #define INCR_COUNT(x) ++x
429431 #else
@@ -1765,6 +1767,16 @@ void *__bound_memset(void *s, int c, size_t n) · 1335 unmodified lines
17651767 return memset(s, c, n);
17661768 }
17671769
1770+void __bound_struct_copy(void *dst,void *src,size_t size)
1771+{
1772+ dprintf(stderr, "Copy struct from %p to %p,size %lx\n",
1773+ src,dst,size);
1774+ INCR_COUNT(bound_struct_copy_count);
1775+ __bound_check(dst,size,"struct copy destination");
1776+ __bound_check(src,size,"struct copy source");
1777+ return;
1778+}
1779+
17681780 #if defined(__arm__) && defined(__ARM_EABI__)
17691781 void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n)
17701782 {
tcc.h+2−0
@@ -1644,6 +1644,8 @@ ST_FUNC void gen_increment_tcov (SValue *sv); · 1643 unmodified lines
16441644
16451645 /* ------------ x86_64-gen.c ------------ */
16461646 #ifdef TCC_TARGET_X86_64
1647+#define TCC_TARGET_NATIVE_STRUCT_COPY
1648+ST_FUNC void gen_struct_copy(int size);
16471649 ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
16481650 ST_FUNC void gen_opl(int op);
16491651 #ifdef TCC_TARGET_PE
tccgen.c+33−2
@@ -3474,9 +3474,38 @@ ST_FUNC void vstore(void) · 3473 unmodified lines
34743474 if (sbt == VT_STRUCT) {
34753475 /* if structure, only generate pointer */
34763476 /* structure assignment : generate memcpy */
3477− /* XXX: optimize if small size */
34783477 size = type_size(&vtop->type, &align);
34793478
3479+#ifdef TCC_TARGET_NATIVE_STRUCT_COPY
3480+ if (size <= (PTR_SIZE << 4)) {
3481+ vswap();
3482+#ifdef CONFIG_TCC_BCHECK
3483+ if (vtop->r & VT_MUSTBOUND)
3484+ gbound();
3485+#endif
3486+ vtop->type.t = VT_PTR;
3487+ gaddrof();
3488+
3489+ vpushv(vtop - 1);
3490+#ifdef CONFIG_TCC_BCHECK
3491+ if (vtop->r & VT_MUSTBOUND)
3492+ gbound();
3493+#endif
3494+ vtop->type.t = VT_PTR;
3495+ gaddrof(); /* src dest src */
3496+#ifdef CONFIG_TCC_BCHECK
3497+ if (tcc_state->do_bounds_check) {
3498+ vpush_helper_func(TOK___bound_struct_copy);
3499+ vpushv(vtop - 2);
3500+ vpushv(vtop - 2);
3501+ vpushi(size);
3502+ gfunc_call(3);
3503+ }
3504+#endif
3505+
3506+ gen_struct_copy(size);
3507+ } else {
3508+#endif
34803509 /* destination */
34813510 vswap();
34823511 #ifdef CONFIG_TCC_BCHECK
@@ -3510,7 +3539,9 @@ ST_FUNC void vstore(void) · 27 unmodified lines
35103539 vpushi(size);
35113540 gfunc_call(3);
35123541 /* leave source on stack */
3513−
3542+#ifdef TCC_TARGET_NATIVE_STRUCT_COPY
3543+ }
3544+#endif
35143545 } else if (ft & VT_BITFIELD) {
35153546 /* bitfield store handling */
35163547
tcctok.h+1−0
@@ -330,6 +330,7 @@ · 329 unmodified lines
330330 DEF(TOK___bound_setjmp, "__bound_setjmp")
331331 DEF(TOK___bound_longjmp, "__bound_longjmp")
332332 DEF(TOK___bound_new_region, "__bound_new_region")
333+ DEF(TOK___bound_struct_copy,"__bound_struct_copy")
333334 # ifdef TCC_TARGET_PE
334335 # ifdef TCC_TARGET_X86_64
335336 DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
x86_64-gen.c+50−0
@@ -2282,6 +2282,56 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { · 2281 unmodified lines
22822282 }
22832283 }
22842284
2285+/*
2286+ * Assmuing the top part of the stack looks like below,
2287+ * src dest src
2288+ */
2289+void gen_struct_copy(int size)
2290+{
2291+ save_reg(TREG_RSI);
2292+ load(TREG_RSI,vtop);
2293+ vtop->r = TREG_RSI;
2294+ vswap(); /* dest src src */
2295+ save_reg(TREG_RDI);
2296+ load(TREG_RDI,vtop);
2297+ vtop->r = TREG_RDI;
2298+ /* Not aligned by 8bytes */
2299+ if (size & 0x04) {
2300+ o(0xa5);
2301+ }
2302+ if (size & 0x02) {
2303+ o(0xa566);
2304+ }
2305+ if (size & 0x01) {
2306+ o(0xa4);
2307+ }
2308+
2309+ size >>= 3;
2310+ if (!size)
2311+ goto done;
2312+ /* Although this function is only called when the struct is smaller */
2313+ /* than 32 bytes(4 * PTR_SIZE),a common implementation is included */
2314+ if (size <= 4 && size) {
2315+ switch (size) {
2316+ case 4: o(0xa548);
2317+ case 3: o(0xa548);
2318+ case 2: o(0xa548);
2319+ case 1: o(0xa548);
2320+ }
2321+ } else {
2322+ save_reg(TREG_RCX);
2323+ vpushi(size);
2324+ load(TREG_RCX,vtop);
2325+ vtop->r = TREG_RCX;
2326+ o(0xa548f3);
2327+ vpop();
2328+ }
2329+done:
2330+ vpop();
2331+ vpop();
2332+ return;
2333+}
2334+
22852335
22862336 /* end of x86-64 code generator */
22872337 /*************************************************************/

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t