aboutsummaryrefslogtreecommitdiffstats
path: root/src/comp.c
diff options
context:
space:
mode:
authorNicolás Bértolo2020-05-20 00:34:32 -0300
committerAndrea Corallo2020-05-31 17:50:07 +0100
commit3efb2808d415f723ade4a0f9f61738e1a707156c (patch)
tree0aacaaa573dea99aee35508721ef625bba1d695c /src/comp.c
parent5cf148cfef23b827629950048dab678f3b9af2d3 (diff)
downloademacs-3efb2808d415f723ade4a0f9f61738e1a707156c.tar.gz
emacs-3efb2808d415f723ade4a0f9f61738e1a707156c.zip
* Cut down compile-time emitting static data as string literals
This change drastically reduce compile time. Apparently GCC optimizer does not scale up well at all for long sequences of assignments into a single array. Nicolás Bértolo <nicolasbertolo@gmail.com> Andrea Corallo <akrl@sdf.org> * src/comp.c (gcc_jit_context_new_string_literal) (gcc_jit_block_add_assignment_op): New imports. (comp_t): New 'size_t_type' 'memcpy' fields. (emit_static_object): Define static objects using string literals and memcpy. (define_memcpy): New function. (Fcomp__init_ctxt): Define 'size_t_type' and 'memcpy'.
Diffstat (limited to 'src/comp.c')
-rw-r--r--src/comp.c120
1 files changed, 105 insertions, 15 deletions
diff --git a/src/comp.c b/src/comp.c
index f288fc2551a..81c4d2fe32a 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -46,6 +46,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
46# include "w32common.h" 46# include "w32common.h"
47 47
48#undef gcc_jit_block_add_assignment 48#undef gcc_jit_block_add_assignment
49#undef gcc_jit_block_add_assignment_op
49#undef gcc_jit_block_add_comment 50#undef gcc_jit_block_add_comment
50#undef gcc_jit_block_add_eval 51#undef gcc_jit_block_add_eval
51#undef gcc_jit_block_end_with_conditional 52#undef gcc_jit_block_end_with_conditional
@@ -75,6 +76,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
75#undef gcc_jit_context_new_rvalue_from_int 76#undef gcc_jit_context_new_rvalue_from_int
76#undef gcc_jit_context_new_rvalue_from_long 77#undef gcc_jit_context_new_rvalue_from_long
77#undef gcc_jit_context_new_rvalue_from_ptr 78#undef gcc_jit_context_new_rvalue_from_ptr
79#undef gcc_jit_context_new_string_literal
78#undef gcc_jit_context_new_struct_type 80#undef gcc_jit_context_new_struct_type
79#undef gcc_jit_context_new_unary_op 81#undef gcc_jit_context_new_unary_op
80#undef gcc_jit_context_new_union_type 82#undef gcc_jit_context_new_union_type
@@ -164,6 +166,8 @@ DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_long,
164 (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, long value)); 166 (gcc_jit_context *ctxt, gcc_jit_type *numeric_type, long value));
165DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_ptr, 167DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_rvalue_from_ptr,
166 (gcc_jit_context *ctxt, gcc_jit_type *pointer_type, void *value)); 168 (gcc_jit_context *ctxt, gcc_jit_type *pointer_type, void *value));
169DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_string_literal,
170 (gcc_jit_context *ctxt, const char *value));
167DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_unary_op, 171DEF_DLL_FN (gcc_jit_rvalue *, gcc_jit_context_new_unary_op,
168 (gcc_jit_context *ctxt, gcc_jit_location *loc, 172 (gcc_jit_context *ctxt, gcc_jit_location *loc,
169 enum gcc_jit_unary_op op, gcc_jit_type *result_type, 173 enum gcc_jit_unary_op op, gcc_jit_type *result_type,
@@ -197,6 +201,10 @@ DEF_DLL_FN (gcc_jit_type *, gcc_jit_type_get_pointer, (gcc_jit_type *type));
197DEF_DLL_FN (void, gcc_jit_block_add_assignment, 201DEF_DLL_FN (void, gcc_jit_block_add_assignment,
198 (gcc_jit_block *block, gcc_jit_location *loc, gcc_jit_lvalue *lvalue, 202 (gcc_jit_block *block, gcc_jit_location *loc, gcc_jit_lvalue *lvalue,
199 gcc_jit_rvalue *rvalue)); 203 gcc_jit_rvalue *rvalue));
204DEF_DLL_FN (void, gcc_jit_block_add_assignment_op,
205 (gcc_jit_block *block, gcc_jit_location *loc,
206 gcc_jit_lvalue *lvalue, enum gcc_jit_binary_op op,
207 gcc_jit_rvalue *rvalue));
200DEF_DLL_FN (void, gcc_jit_block_add_eval, 208DEF_DLL_FN (void, gcc_jit_block_add_eval,
201 (gcc_jit_block *block, gcc_jit_location *loc, 209 (gcc_jit_block *block, gcc_jit_location *loc,
202 gcc_jit_rvalue *rvalue)); 210 gcc_jit_rvalue *rvalue));
@@ -239,6 +247,7 @@ init_gccjit_functions (void)
239 247
240 /* In alphabetical order */ 248 /* In alphabetical order */
241 LOAD_DLL_FN (library, gcc_jit_block_add_assignment); 249 LOAD_DLL_FN (library, gcc_jit_block_add_assignment);
250 LOAD_DLL_FN (library, gcc_jit_block_add_assignment_op);
242 LOAD_DLL_FN (library, gcc_jit_block_add_comment); 251 LOAD_DLL_FN (library, gcc_jit_block_add_comment);
243 LOAD_DLL_FN (library, gcc_jit_block_add_eval); 252 LOAD_DLL_FN (library, gcc_jit_block_add_eval);
244 LOAD_DLL_FN (library, gcc_jit_block_end_with_conditional); 253 LOAD_DLL_FN (library, gcc_jit_block_end_with_conditional);
@@ -268,6 +277,7 @@ init_gccjit_functions (void)
268 LOAD_DLL_FN (library, gcc_jit_context_new_rvalue_from_int); 277 LOAD_DLL_FN (library, gcc_jit_context_new_rvalue_from_int);
269 LOAD_DLL_FN (library, gcc_jit_context_new_rvalue_from_long); 278 LOAD_DLL_FN (library, gcc_jit_context_new_rvalue_from_long);
270 LOAD_DLL_FN (library, gcc_jit_context_new_rvalue_from_ptr); 279 LOAD_DLL_FN (library, gcc_jit_context_new_rvalue_from_ptr);
280 LOAD_DLL_FN (library, gcc_jit_context_new_string_literal);
271 LOAD_DLL_FN (library, gcc_jit_context_new_struct_type); 281 LOAD_DLL_FN (library, gcc_jit_context_new_struct_type);
272 LOAD_DLL_FN (library, gcc_jit_context_new_unary_op); 282 LOAD_DLL_FN (library, gcc_jit_context_new_unary_op);
273 LOAD_DLL_FN (library, gcc_jit_context_new_union_type); 283 LOAD_DLL_FN (library, gcc_jit_context_new_union_type);
@@ -296,6 +306,7 @@ init_gccjit_functions (void)
296 306
297/* In alphabetical order */ 307/* In alphabetical order */
298#define gcc_jit_block_add_assignment fn_gcc_jit_block_add_assignment 308#define gcc_jit_block_add_assignment fn_gcc_jit_block_add_assignment
309#define gcc_jit_block_add_assignment_op fn_gcc_jit_block_add_assignment_op
299#define gcc_jit_block_add_comment fn_gcc_jit_block_add_comment 310#define gcc_jit_block_add_comment fn_gcc_jit_block_add_comment
300#define gcc_jit_block_add_eval fn_gcc_jit_block_add_eval 311#define gcc_jit_block_add_eval fn_gcc_jit_block_add_eval
301#define gcc_jit_block_end_with_conditional fn_gcc_jit_block_end_with_conditional 312#define gcc_jit_block_end_with_conditional fn_gcc_jit_block_end_with_conditional
@@ -325,6 +336,7 @@ init_gccjit_functions (void)
325#define gcc_jit_context_new_rvalue_from_int fn_gcc_jit_context_new_rvalue_from_int 336#define gcc_jit_context_new_rvalue_from_int fn_gcc_jit_context_new_rvalue_from_int
326#define gcc_jit_context_new_rvalue_from_long fn_gcc_jit_context_new_rvalue_from_long 337#define gcc_jit_context_new_rvalue_from_long fn_gcc_jit_context_new_rvalue_from_long
327#define gcc_jit_context_new_rvalue_from_ptr fn_gcc_jit_context_new_rvalue_from_ptr 338#define gcc_jit_context_new_rvalue_from_ptr fn_gcc_jit_context_new_rvalue_from_ptr
339#define gcc_jit_context_new_string_literal fn_gcc_jit_context_new_string_literal
328#define gcc_jit_context_new_struct_type fn_gcc_jit_context_new_struct_type 340#define gcc_jit_context_new_struct_type fn_gcc_jit_context_new_struct_type
329#define gcc_jit_context_new_unary_op fn_gcc_jit_context_new_unary_op 341#define gcc_jit_context_new_unary_op fn_gcc_jit_context_new_unary_op
330#define gcc_jit_context_new_union_type fn_gcc_jit_context_new_union_type 342#define gcc_jit_context_new_union_type fn_gcc_jit_context_new_union_type
@@ -462,6 +474,7 @@ typedef struct {
462 gcc_jit_type *char_ptr_type; 474 gcc_jit_type *char_ptr_type;
463 gcc_jit_type *ptrdiff_type; 475 gcc_jit_type *ptrdiff_type;
464 gcc_jit_type *uintptr_type; 476 gcc_jit_type *uintptr_type;
477 gcc_jit_type *size_t_type;
465#if LISP_WORDS_ARE_POINTERS 478#if LISP_WORDS_ARE_POINTERS
466 gcc_jit_type *lisp_X; 479 gcc_jit_type *lisp_X;
467#endif 480#endif
@@ -548,6 +561,7 @@ typedef struct {
548 gcc_jit_rvalue *data_relocs_ephemeral; 561 gcc_jit_rvalue *data_relocs_ephemeral;
549 /* Synthesized struct holding func relocs. */ 562 /* Synthesized struct holding func relocs. */
550 gcc_jit_lvalue *func_relocs; 563 gcc_jit_lvalue *func_relocs;
564 gcc_jit_function *memcpy;
551 Lisp_Object d_default_idx; 565 Lisp_Object d_default_idx;
552 Lisp_Object d_impure_idx; 566 Lisp_Object d_impure_idx;
553 Lisp_Object d_ephemeral_idx; 567 Lisp_Object d_ephemeral_idx;
@@ -2347,7 +2361,7 @@ emit_static_object (const char *name, Lisp_Object obj)
2347 /* libgccjit has no support for initialized static data. 2361 /* libgccjit has no support for initialized static data.
2348 The mechanism below is certainly not aesthetic but I assume the bottle neck 2362 The mechanism below is certainly not aesthetic but I assume the bottle neck
2349 in terms of performance at load time will still be the reader. 2363 in terms of performance at load time will still be the reader.
2350 NOTE: we can not relay on libgccjit even for valid NULL terminated C 2364 NOTE: we can not rely on libgccjit even for valid NULL terminated C
2351 strings cause of this funny bug that will affect all pre gcc10 era gccs: 2365 strings cause of this funny bug that will affect all pre gcc10 era gccs:
2352 https://gcc.gnu.org/ml/jit/2019-q3/msg00013.html */ 2366 https://gcc.gnu.org/ml/jit/2019-q3/msg00013.html */
2353 2367
@@ -2405,22 +2419,78 @@ emit_static_object (const char *name, Lisp_Object obj)
2405 gcc_jit_lvalue *arr = 2419 gcc_jit_lvalue *arr =
2406 gcc_jit_lvalue_access_field (data_struct, NULL, fields[1]); 2420 gcc_jit_lvalue_access_field (data_struct, NULL, fields[1]);
2407 2421
2408 for (ptrdiff_t i = 0; i < len; i++, p++) 2422 gcc_jit_lvalue *ptrvar = gcc_jit_function_new_local (f, NULL,
2423 comp.char_ptr_type,
2424 "ptr");
2425
2426 gcc_jit_block_add_assignment (
2427 block,
2428 NULL,
2429 ptrvar,
2430 gcc_jit_lvalue_get_address (
2431 gcc_jit_context_new_array_access (
2432 comp.ctxt,
2433 NULL,
2434 gcc_jit_lvalue_as_rvalue (arr),
2435 gcc_jit_context_new_rvalue_from_int (comp.ctxt, comp.int_type, 0)),
2436 NULL));
2437
2438 for (ptrdiff_t i = 0; i < len;)
2409 { 2439 {
2410 gcc_jit_block_add_assignment ( 2440 /* We can't use string literals longer that 200 bytes because
2411 block, 2441 they cause a crash in older versions of gccjit.
2412 NULL, 2442 https://gcc.gnu.org/ml/jit/2019-q3/msg00013.html. */
2413 gcc_jit_context_new_array_access ( 2443 char str[200];
2414 comp.ctxt, 2444 strncpy (str, p, 200);
2415 NULL, 2445 str[199] = 0;
2416 gcc_jit_lvalue_as_rvalue (arr), 2446 uintptr_t l = strlen (str);
2417 gcc_jit_context_new_rvalue_from_int (comp.ctxt, 2447
2418 comp.ptrdiff_type, 2448 if (l != 0)
2419 i)), 2449 {
2420 gcc_jit_context_new_rvalue_from_int (comp.ctxt, 2450 p += l;
2421 comp.char_type, 2451 i += l;
2422 *p)); 2452
2453 gcc_jit_rvalue *args[3]
2454 = {gcc_jit_lvalue_as_rvalue (ptrvar),
2455 gcc_jit_context_new_string_literal (comp.ctxt, str),
2456 gcc_jit_context_new_rvalue_from_int (comp.ctxt,
2457 comp.size_t_type,
2458 l)};
2459
2460 gcc_jit_block_add_eval (block, NULL,
2461 gcc_jit_context_new_call (comp.ctxt, NULL,
2462 comp.memcpy,
2463 ARRAYELTS (args),
2464 args));
2465 gcc_jit_block_add_assignment (block, NULL, ptrvar,
2466 gcc_jit_lvalue_get_address (
2467 gcc_jit_context_new_array_access (comp.ctxt, NULL,
2468 gcc_jit_lvalue_as_rvalue (ptrvar),
2469 gcc_jit_context_new_rvalue_from_int (comp.ctxt,
2470 comp.uintptr_type,
2471 l)),
2472 NULL));
2473 }
2474 else
2475 {
2476 /* If strlen returned 0 that means that the static object
2477 contains a NULL byte. In that case just move over to the
2478 next block. We can rely on the byte being zero because
2479 of the previous call to bzero and because the dynamic
2480 linker cleared it. */
2481 p++;
2482 i++;
2483 gcc_jit_block_add_assignment (
2484 block, NULL, ptrvar,
2485 gcc_jit_lvalue_get_address (
2486 gcc_jit_context_new_array_access (
2487 comp.ctxt, NULL, gcc_jit_lvalue_as_rvalue (ptrvar),
2488 gcc_jit_context_new_rvalue_from_int (comp.ctxt,
2489 comp.uintptr_type, 1)),
2490 NULL));
2491 }
2423 } 2492 }
2493
2424 gcc_jit_block_add_assignment ( 2494 gcc_jit_block_add_assignment (
2425 block, 2495 block,
2426 NULL, 2496 NULL,
@@ -2766,6 +2836,21 @@ define_jmp_buf (void)
2766 1, &field); 2836 1, &field);
2767} 2837}
2768 2838
2839static void
2840define_memcpy (void)
2841{
2842
2843 gcc_jit_param *params[] =
2844 { gcc_jit_context_new_param (comp.ctxt, NULL, comp.void_ptr_type, "dest"),
2845 gcc_jit_context_new_param (comp.ctxt, NULL, comp.void_ptr_type, "src"),
2846 gcc_jit_context_new_param (comp.ctxt, NULL, comp.size_t_type, "n") };
2847
2848 comp.memcpy =
2849 gcc_jit_context_new_function (comp.ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED,
2850 comp.void_ptr_type, "memcpy",
2851 ARRAYELTS (params), params, false);
2852}
2853
2769/* struct handler definition */ 2854/* struct handler definition */
2770 2855
2771static void 2856static void
@@ -3772,6 +3857,9 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
3772 comp.uintptr_type = gcc_jit_context_get_int_type (comp.ctxt, 3857 comp.uintptr_type = gcc_jit_context_get_int_type (comp.ctxt,
3773 sizeof (void *), 3858 sizeof (void *),
3774 false); 3859 false);
3860 comp.size_t_type = gcc_jit_context_get_int_type (comp.ctxt,
3861 sizeof (size_t),
3862 false);
3775 3863
3776 comp.exported_funcs_h = CALLN (Fmake_hash_table, QCtest, Qequal); 3864 comp.exported_funcs_h = CALLN (Fmake_hash_table, QCtest, Qequal);
3777 /* 3865 /*
@@ -3780,6 +3868,8 @@ DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
3780 */ 3868 */
3781 comp.imported_funcs_h = CALLN (Fmake_hash_table); 3869 comp.imported_funcs_h = CALLN (Fmake_hash_table);
3782 3870
3871 define_memcpy ();
3872
3783 /* Define data structures. */ 3873 /* Define data structures. */
3784 3874
3785 define_lisp_cons (); 3875 define_lisp_cons ();