* Speedups/Cleanups: End of GSOC patch collection
@ 2012-08-18 11:19 Dimitrios Apostolou
2012-08-18 11:50 ` Dimitrios Apostolou
` (8 more replies)
0 siblings, 9 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-18 11:19 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev, jimis
Hello list,
for the following couple of days I'll be posting under this thread my
collection of patches.
Unless otherwise mentioned they've been bootstrapped and tested on x86,
but with a three-weeks old snapshot, that is pre-C++ conversion. I plan to
test again next week with a latest snapshot, so please wait for it before
applying.
Most things are minor changes and tweaks, some are ported patches from
last year, some are new. I also have some bigger patches that are flawed
(some don't even compile) either because of difficulties I encountered or
simply lack of time. I 'll try and post what is presentable from them, I'd
appreciate discussion on whether/how to continue with those.
Thanks,
Dimitris
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Speedups/Cleanups: End of GSOC patch collection
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
@ 2012-08-18 11:50 ` Dimitrios Apostolou
2012-08-18 16:37 ` Dimitrios Apostolou
` (7 subsequent siblings)
8 siblings, 0 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-18 11:50 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 818 bytes --]
2012-08-18 Dimitrios Apostolou <jimis@gmx.net>
* dwarf2out.c (output_indirect_string): Use
ASM_OUTPUT_INTERNAL_LABEL instead of slower ASM_OUTPUT_LABEL.
* varasm.c (assemble_string): Don't break string in chunks, this
is assembler specific and already done in most versions of
ASM_OUTPUT_ASCII.
I think there is no correctness issue regarding output_indirect_string()
since .debug_str are always compiler generated labels, and this gives a
small speedup with -g3 debug info.
And regarding assemble_string() I find it superfluous to break it in two
places. I found only the following versions of ASM_OUTPUT_ASCII not caring
about string length, I guess the assemblers don't have a limit:
arm.c: vmsdbgout.c:ASM_OUTPUT_ASCII
picochip.c: picochip_output_ascii()
pdp11.c: output_ascii()
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/PLAIN, Size: 614 bytes --]
=== modified file 'gcc/varasm.c'
--- gcc/varasm.c 2012-08-15 01:56:07 +0000
+++ gcc/varasm.c 2012-08-16 06:12:28 +0000
@@ -1726,22 +1726,7 @@ assemble_align (int align)
void
assemble_string (const char *p, int size)
{
- int pos = 0;
- int maximum = 2000;
-
- /* If the string is very long, split it up. */
-
- while (pos < size)
- {
- int thissize = size - pos;
- if (thissize > maximum)
- thissize = maximum;
-
- ASM_OUTPUT_ASCII (asm_out_file, p, thissize);
-
- pos += thissize;
- p += thissize;
- }
+ ASM_OUTPUT_ASCII (asm_out_file, p, size);
}
[-- Attachment #3: Type: TEXT/PLAIN, Size: 474 bytes --]
=== modified file 'gcc/dwarf2out.c'
--- gcc/dwarf2out.c 2012-08-15 01:56:07 +0000
+++ gcc/dwarf2out.c 2012-08-16 06:19:19 +0000
@@ -20887,7 +20887,7 @@ output_indirect_string (void **h, void *
if (node->form == DW_FORM_strp)
{
switch_to_section (debug_str_section);
- ASM_OUTPUT_LABEL (asm_out_file, node->label);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, node->label);
assemble_string (node->str, strlen (node->str) + 1);
}
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Speedups/Cleanups: End of GSOC patch collection
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
2012-08-18 11:50 ` Dimitrios Apostolou
@ 2012-08-18 16:37 ` Dimitrios Apostolou
2012-08-20 9:20 ` Dodji Seketeli
2012-08-18 18:10 ` [graphds.h] Allocate graph from obstack Dimitrios Apostolou
` (6 subsequent siblings)
8 siblings, 1 reply; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-18 16:37 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev, Ian Lance Taylor
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1014 bytes --]
Hi, these are the type-safe obstack macros that I use in other patches. As
requested, I also changed XOBFINISH to return (T *) and changed all
callers, felt a little strange to change (char *) to char. I also replaced
all _obstack_begin() calls in libcpp with obstack_init() which is the
documented way of allocating macros.
2012-08-18 Dimitrios Apostolou <jimis@gmx.net>
* include/libiberty.h (XOBDELETE, XOBGROW, XOBGROWVEC, XOBSHRINK)
(XOBSHRINKVEC, XOBFINISH): New type-safe macros for obstack
operations.
(XOBFINISH): Changed to return (T *) instead of T. All callers
updated.
* libcpp/include/symtab.h (obstack_chunk_alloc)
(obstack_chunk_free): Define, so that obstack_init() can be used.
* libcpp/internal.h (struct cset_converter): Same.
* libcpp/files.c (_cpp_init_files): Changed _obstack_begin() to
obstack_init().
* libcpp/identifiers.c (_cpp_init_hashtable): Same.
* libcpp/symtab.c (ht_create): Same.
* libcpp/init.c (cpp_create_reader): Same.
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/plain, Size: 26481 bytes --]
2012-08-18 Dimitrios Apostolou <jimis@gmx.net>
* include/libiberty.h (XOBDELETE, XOBGROW, XOBGROWVEC, XOBSHRINK)
(XOBSHRINKVEC, XOBFINISH): New type-safe macros for obstack
operations.
(XOBFINISH): Changed to return (T *) instead of T. All callers
updated.
* libcpp/include/symtab.h (obstack_chunk_alloc)
(obstack_chunk_free): Define, so that obstack_init() can be used.
* libcpp/internal.h (struct cset_converter): Same.
* libcpp/files.c (_cpp_init_files): Changed _obstack_begin() to
obstack_init().
* libcpp/identifiers.c (_cpp_init_hashtable): Same.
* libcpp/symtab.c (ht_create): Same.
* libcpp/init.c (cpp_create_reader): Same.
=== modified file 'gcc/c-family/c-lex.c'
--- gcc/c-family/c-lex.c 2012-06-19 19:55:33 +0000
+++ gcc/c-family/c-lex.c 2012-08-18 13:42:37 +0000
@@ -1037,7 +1037,7 @@ lex_string (const cpp_token *tok, tree *
/* We have read one more token than we want. */
_cpp_backup_tokens (parse_in, 1);
if (concats)
- strs = XOBFINISH (&str_ob, cpp_string *);
+ strs = XOBFINISH (&str_ob, cpp_string);
if (concats && !objc_string && !in_system_header)
warning (OPT_Wtraditional,
=== modified file 'gcc/collect2.c'
--- gcc/collect2.c 2012-05-31 20:19:00 +0000
+++ gcc/collect2.c 2012-08-18 13:42:51 +0000
@@ -514,7 +514,7 @@ extract_string (const char **pp)
obstack_1grow (&temporary_obstack, '\0');
*pp = p;
- return XOBFINISH (&temporary_obstack, char *);
+ return XOBFINISH (&temporary_obstack, char);
}
\f
void
@@ -535,7 +535,7 @@ dump_ld_file (const char *name, FILE *to
const char *word, *p;
char *result;
obstack_1grow (&temporary_obstack, '\0');
- word = XOBFINISH (&temporary_obstack, const char *);
+ word = XOBFINISH (&temporary_obstack, const char);
if (*word == '.')
++word, putc ('.', to);
@@ -943,7 +943,7 @@ maybe_run_lto_and_relink (char **lto_ld_
lto_o_files = XNEWVEC (char *, num_files + 1);
lto_o_files[num_files] = NULL;
- start = XOBFINISH (&temporary_obstack, char *);
+ start = XOBFINISH (&temporary_obstack, char);
for (i = 0; i < num_files; ++i)
{
end = start;
=== modified file 'gcc/dbxout.c'
--- gcc/dbxout.c 2012-06-24 17:58:46 +0000
+++ gcc/dbxout.c 2012-08-18 13:48:19 +0000
@@ -864,7 +864,7 @@ dbxout_finish_complex_stabs (tree sym, s
obstack_1grow (&stabstr_ob, '\0');
len = obstack_object_size (&stabstr_ob);
- chunk = str = XOBFINISH (&stabstr_ob, char *);
+ chunk = str = XOBFINISH (&stabstr_ob, char);
/* Within the buffer are a sequence of NUL-separated strings,
each of which is to be written out as a separate stab
@@ -897,7 +897,7 @@ dbxout_finish_complex_stabs (tree sym, s
comma than to do a two-character fputs. */
obstack_grow (&stabstr_ob, "\",", 2);
len = obstack_object_size (&stabstr_ob);
- str = XOBFINISH (&stabstr_ob, char *);
+ str = XOBFINISH (&stabstr_ob, char);
fwrite (str, 1, len, asm_out_file);
DBX_FINISH_STABS (sym, code, line, addr, label, number);
=== modified file 'gcc/gcc.c'
--- gcc/gcc.c 2012-08-15 01:56:07 +0000
+++ gcc/gcc.c 2012-08-18 13:47:06 +0000
@@ -1435,7 +1435,7 @@ init_spec (void)
}
obstack_1grow (&obstack, '\0');
- libgcc_spec = XOBFINISH (&obstack, const char *);
+ libgcc_spec = XOBFINISH (&obstack, const char);
}
#endif
#ifdef USE_AS_TRADITIONAL_FORMAT
@@ -1444,7 +1444,7 @@ init_spec (void)
static const char tf[] = "--traditional-format ";
obstack_grow (&obstack, tf, sizeof(tf) - 1);
obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
- asm_spec = XOBFINISH (&obstack, const char *);
+ asm_spec = XOBFINISH (&obstack, const char);
}
#endif
@@ -1469,7 +1469,7 @@ init_spec (void)
}
# endif
obstack_grow0 (&obstack, link_spec, strlen (link_spec));
- link_spec = XOBFINISH (&obstack, const char *);
+ link_spec = XOBFINISH (&obstack, const char);
#endif
specs = sl;
@@ -2277,7 +2277,7 @@ build_search_list (const struct path_pre
for_each_path (paths, do_multi, 0, add_to_obstack, &info);
obstack_1grow (&collect_obstack, '\0');
- return XOBFINISH (&collect_obstack, char *);
+ return XOBFINISH (&collect_obstack, char);
}
/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
@@ -2924,7 +2924,7 @@ convert_filename (const char *name, int
{
obstack_grow (&obstack, name, len - 2);
obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
- name = XOBFINISH (&obstack, const char *);
+ name = XOBFINISH (&obstack, const char);
}
#endif
@@ -2945,7 +2945,7 @@ convert_filename (const char *name, int
obstack_grow (&obstack, name, len);
obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
strlen (TARGET_EXECUTABLE_SUFFIX));
- name = XOBFINISH (&obstack, const char *);
+ name = XOBFINISH (&obstack, const char);
#endif
return name;
@@ -4047,7 +4047,7 @@ set_collect_gcc_options (void)
}
}
obstack_grow (&collect_obstack, "\0", 1);
- xputenv (XOBFINISH (&collect_obstack, char *));
+ xputenv (XOBFINISH (&collect_obstack, char));
}
\f
/* Process a spec string, accumulating and running commands. */
@@ -4117,7 +4117,7 @@ end_going_arg (void)
const char *string;
obstack_1grow (&obstack, 0);
- string = XOBFINISH (&obstack, const char *);
+ string = XOBFINISH (&obstack, const char);
if (this_is_library_file)
string = find_file (string);
if (this_is_linker_script)
@@ -6242,21 +6242,21 @@ main (int argc, char **argv)
obstack_grow (&multilib_obstack, p, strlen (p));
obstack_1grow (&multilib_obstack, 0);
- multilib_select = XOBFINISH (&multilib_obstack, const char *);
+ multilib_select = XOBFINISH (&multilib_obstack, const char);
q = multilib_matches_raw;
while ((p = *q++) != (char *) 0)
obstack_grow (&multilib_obstack, p, strlen (p));
obstack_1grow (&multilib_obstack, 0);
- multilib_matches = XOBFINISH (&multilib_obstack, const char *);
+ multilib_matches = XOBFINISH (&multilib_obstack, const char);
q = multilib_exclusions_raw;
while ((p = *q++) != (char *) 0)
obstack_grow (&multilib_obstack, p, strlen (p));
obstack_1grow (&multilib_obstack, 0);
- multilib_exclusions = XOBFINISH (&multilib_obstack, const char *);
+ multilib_exclusions = XOBFINISH (&multilib_obstack, const char);
need_space = FALSE;
for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
@@ -6270,7 +6270,7 @@ main (int argc, char **argv)
}
obstack_1grow (&multilib_obstack, 0);
- multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
+ multilib_defaults = XOBFINISH (&multilib_obstack, const char);
}
#ifdef INIT_ENVIRONMENT
@@ -6357,7 +6357,7 @@ main (int argc, char **argv)
{
obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
obstack_grow0 (&obstack, link_spec, strlen (link_spec));
- set_spec ("link", XOBFINISH (&obstack, const char *), false);
+ set_spec ("link", XOBFINISH (&obstack, const char), false);
}
#endif
@@ -6508,7 +6508,7 @@ main (int argc, char **argv)
obstack_init (&collect_obstack);
obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
obstack_grow (&collect_obstack, argv[0], strlen (argv[0]) + 1);
- xputenv (XOBFINISH (&collect_obstack, char *));
+ xputenv (XOBFINISH (&collect_obstack, char));
/* Set up to remember the pathname of the lto wrapper. */
@@ -6525,7 +6525,7 @@ main (int argc, char **argv)
sizeof ("COLLECT_LTO_WRAPPER=") - 1);
obstack_grow (&collect_obstack, lto_wrapper_spec,
strlen (lto_wrapper_spec) + 1);
- xputenv (XOBFINISH (&collect_obstack, char *));
+ xputenv (XOBFINISH (&collect_obstack, char));
}
/* Reject switches that no pass was interested in. */
@@ -6665,7 +6665,7 @@ warranty; not even for MERCHANTABILITY o
obstack_init (&obstack);
do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
obstack_1grow (&obstack, '\0');
- thrmod = XOBFINISH (&obstack, const char *);
+ thrmod = XOBFINISH (&obstack, const char);
#else
thrmod = thread_model;
#endif
@@ -7391,7 +7391,7 @@ set_multilib_dir (void)
obstack_grow (&multilib_obstack, start, end - start);
obstack_1grow (&multilib_obstack, 0);
- mdswitches[i].str = XOBFINISH (&multilib_obstack, const char *);
+ mdswitches[i].str = XOBFINISH (&multilib_obstack, const char);
mdswitches[i++].len = end - start;
if (*end == '\0')
=== modified file 'gcc/genflags.c'
--- gcc/genflags.c 2011-01-03 20:52:22 +0000
+++ gcc/genflags.c 2012-08-18 13:47:29 +0000
@@ -286,7 +286,7 @@ main (int argc, char **argv)
/* Print out the prototypes now. */
dummy = (rtx) 0;
obstack_grow (&obstack, &dummy, sizeof (rtx));
- insns = XOBFINISH (&obstack, rtx *);
+ insns = XOBFINISH (&obstack, rtx);
for (insn_ptr = insns; *insn_ptr; insn_ptr++)
gen_proto (*insn_ptr);
=== modified file 'gcc/gengtype-state.c'
--- gcc/gengtype-state.c 2012-08-15 01:56:07 +0000
+++ gcc/gengtype-state.c 2012-08-18 13:45:57 +0000
@@ -306,7 +306,7 @@ read_a_state_token (void)
if (c >= 0)
ungetc (c, state_file);
obstack_1grow (&id_obstack, (char) 0);
- ids = XOBFINISH (&id_obstack, char *);
+ ids = XOBFINISH (&id_obstack, char);
sid = state_ident_by_name (ids, INSERT);
obstack_free (&id_obstack, NULL);
ids = NULL;
@@ -403,7 +403,7 @@ read_a_state_token (void)
if (c != '"')
fatal_reading_state (NULL_STATE_TOKEN, "Unterminated string");
obstack_1grow (&bstring_obstack, '\0');
- cstr = XOBFINISH (&bstring_obstack, char *);
+ cstr = XOBFINISH (&bstring_obstack, char);
cslen = strlen (cstr);
tk = (struct state_token_st *)
xcalloc (sizeof (struct state_token_st) + cslen, 1);
=== modified file 'gcc/gengtype.c'
--- gcc/gengtype.c 2012-08-15 01:56:07 +0000
+++ gcc/gengtype.c 2012-08-18 13:41:45 +0000
@@ -2033,7 +2033,7 @@ matching_file_name_substitute (const cha
obstack_1grow (&str_obstack, c);
}
obstack_1grow (&str_obstack, '\0');
- rawstr = XOBFINISH (&str_obstack, char *);
+ rawstr = XOBFINISH (&str_obstack, char);
str = xstrdup (rawstr);
obstack_free (&str_obstack, NULL);
DBGPRINTF ("matched replacement %s", str);
=== modified file 'gcc/genpreds.c'
--- gcc/genpreds.c 2011-04-12 12:51:10 +0000
+++ gcc/genpreds.c 2012-08-18 13:47:57 +0000
@@ -138,7 +138,7 @@ write_predicate_subfunction (struct pred
obstack_grow (rtl_obstack, p->name, strlen (p->name));
obstack_grow (rtl_obstack, "_1 (op, mode)",
sizeof "_1 (op, mode)");
- match_test_str = XOBFINISH (rtl_obstack, const char *);
+ match_test_str = XOBFINISH (rtl_obstack, const char);
/* Add the function-call expression to the complete expression to be
evaluated. */
@@ -703,7 +703,7 @@ mangle (const char *name)
}
obstack_1grow (rtl_obstack, '\0');
- return XOBFINISH (rtl_obstack, const char *);
+ return XOBFINISH (rtl_obstack, const char);
}
/* Add one constraint, of any sort, to the tables. NAME is its name;
=== modified file 'gcc/gensupport.c'
--- gcc/gensupport.c 2012-07-09 08:45:12 +0000
+++ gcc/gensupport.c 2012-08-18 13:42:59 +0000
@@ -1297,7 +1297,7 @@ gen_mnemonic_setattr (htab_t mnemonic_ht
obstack_1grow (&string_obstack, '\0');
set_attr = rtx_alloc (SET_ATTR);
- XSTR (set_attr, 1) = XOBFINISH (&string_obstack, char *);
+ XSTR (set_attr, 1) = XOBFINISH (&string_obstack, char);
attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
strcpy (attr_name, MNEMONIC_ATTR_NAME);
XSTR (set_attr, 0) = attr_name;
@@ -1388,7 +1388,7 @@ gen_mnemonic_attr (void)
/* Replace the last ',' with the zero end character. */
*((char *)obstack_next_free (&string_obstack) - 1) = '\0';
- XSTR (mnemonic_attr, 1) = XOBFINISH (&string_obstack, char *);
+ XSTR (mnemonic_attr, 1) = XOBFINISH (&string_obstack, char);
}
/* The entry point for initializing the reader. */
=== modified file 'gcc/java/class.c'
--- gcc/java/class.c 2012-08-15 01:56:07 +0000
+++ gcc/java/class.c 2012-08-18 13:46:10 +0000
@@ -2458,7 +2458,7 @@ layout_class (tree this_class)
obstack_grow (&temporary_obstack, buffer, strlen (buffer));
}
obstack_1grow (&temporary_obstack, '\0');
- report = XOBFINISH (&temporary_obstack, char *);
+ report = XOBFINISH (&temporary_obstack, char);
cyclic_inheritance_report = ggc_strdup (report);
obstack_free (&temporary_obstack, report);
TYPE_SIZE (this_class) = error_mark_node;
=== modified file 'gcc/java/jvgenmain.c'
--- gcc/java/jvgenmain.c 2012-07-11 08:58:58 +0000
+++ gcc/java/jvgenmain.c 2012-08-18 13:46:02 +0000
@@ -192,5 +192,5 @@ do_mangle_classname (const char *string)
append_gpp_mangled_name (&ptr [-count], count);
obstack_grow (mangle_obstack, "6class$E", strlen ("6class$E"));
obstack_1grow (mangle_obstack, '\0');
- return XOBFINISH (mangle_obstack, char *);
+ return XOBFINISH (mangle_obstack, char);
}
=== modified file 'gcc/lto-opts.c'
--- gcc/lto-opts.c 2011-11-08 13:41:57 +0000
+++ gcc/lto-opts.c 2012-08-18 13:47:24 +0000
@@ -124,7 +124,7 @@ lto_write_options (void)
option->canonical_option[j]);
}
obstack_grow (&temporary_obstack, "\0", 1);
- args = XOBFINISH (&temporary_obstack, char *);
+ args = XOBFINISH (&temporary_obstack, char);
lto_output_data_stream (&stream, args, strlen (args) + 1);
lto_write_stream (&stream);
=== modified file 'gcc/lto-wrapper.c'
--- gcc/lto-wrapper.c 2012-05-29 14:14:06 +0000
+++ gcc/lto-wrapper.c 2012-08-18 13:48:07 +0000
@@ -336,7 +336,7 @@ get_options_from_collect_gcc_options (co
obstack_ptr_grow (&argv_obstack, NULL);
argc = obstack_object_size (&argv_obstack) / sizeof (void *) - 1;
- argv = XOBFINISH (&argv_obstack, const char **);
+ argv = XOBFINISH (&argv_obstack, const char *);
decode_cmdline_options_to_array (argc, (const char **)argv,
lang_mask,
@@ -732,7 +732,7 @@ run_gcc (unsigned argc, char *argv[])
obstack_ptr_grow (&argv_obstack, argv[i]);
obstack_ptr_grow (&argv_obstack, NULL);
- new_argv = XOBFINISH (&argv_obstack, const char **);
+ new_argv = XOBFINISH (&argv_obstack, const char *);
argv_ptr = &new_argv[new_head_argc];
fork_execute (CONST_CAST (char **, new_argv));
@@ -807,7 +807,7 @@ cont:
the resulting name to the LTRANS output list. */
obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
- output_name = XOBFINISH (&env_obstack, char *);
+ output_name = XOBFINISH (&env_obstack, char);
/* Adjust the dumpbase if the linker output file was seen. */
if (linker_output)
=== modified file 'gcc/objc/objc-encoding.c'
--- gcc/objc/objc-encoding.c 2012-06-29 16:12:35 +0000
+++ gcc/objc/objc-encoding.c 2012-08-18 13:48:31 +0000
@@ -164,7 +164,7 @@ encode_method_prototype (tree method_dec
finish_encoding:
obstack_1grow (&util_obstack, '\0');
- result = get_identifier (XOBFINISH (&util_obstack, char *));
+ result = get_identifier (XOBFINISH (&util_obstack, char));
obstack_free (&util_obstack, util_firstobj);
return result;
}
@@ -179,7 +179,7 @@ objc_build_encode_expr (tree type)
encode_type (type, obstack_object_size (&util_obstack),
OBJC_ENCODE_INLINE_DEFS);
obstack_1grow (&util_obstack, 0); /* null terminate string */
- string = XOBFINISH (&util_obstack, const char *);
+ string = XOBFINISH (&util_obstack, const char);
/* Synthesize a string that represents the encoded struct/union. */
result = my_build_string (strlen (string) + 1, string);
@@ -847,7 +847,7 @@ encode_field_decl (tree field_decl)
obstack_1grow (&util_obstack, 0);
/* Get identifier for the string. */
- result = get_identifier (XOBFINISH (&util_obstack, char *));
+ result = get_identifier (XOBFINISH (&util_obstack, char));
obstack_free (&util_obstack, util_firstobj);
return result;
@@ -945,7 +945,7 @@ objc_v2_encode_prop_attr (tree property)
/* NULL-terminate string. */
obstack_1grow (&util_obstack, 0);
- string = XOBFINISH (&util_obstack, char *);
+ string = XOBFINISH (&util_obstack, char);
obstack_free (&util_obstack, util_firstobj);
return get_identifier (string);
}
=== modified file 'gcc/pretty-print.c'
--- gcc/pretty-print.c 2012-08-07 22:14:29 +0000
+++ gcc/pretty-print.c 2012-08-18 13:47:40 +0000
@@ -273,7 +273,7 @@ pp_base_format (pretty_printer *pp, text
/* Handled in phase 2. Terminate the plain chunk here. */
obstack_1grow (&buffer->chunk_obstack, '\0');
gcc_assert (chunk < PP_NL_ARGMAX * 2);
- args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char);
break;
}
@@ -352,12 +352,12 @@ pp_base_format (pretty_printer *pp, text
obstack_1grow (&buffer->chunk_obstack, '\0');
gcc_assert (chunk < PP_NL_ARGMAX * 2);
- args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char);
}
obstack_1grow (&buffer->chunk_obstack, '\0');
gcc_assert (chunk < PP_NL_ARGMAX * 2);
- args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char);
args[chunk] = 0;
/* Set output to the argument obstack, and switch line-wrapping and
@@ -515,7 +515,7 @@ pp_base_format (pretty_printer *pp, text
pp_string (pp, close_quote);
obstack_1grow (&buffer->chunk_obstack, '\0');
- *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char);
}
#ifdef ENABLE_CHECKING
=== modified file 'gcc/read-md.c'
--- gcc/read-md.c 2012-05-04 20:04:47 +0000
+++ gcc/read-md.c 2012-08-18 13:47:51 +0000
@@ -206,7 +206,7 @@ join_c_conditions (const char *cond1, co
obstack_ptr_grow (&joined_conditions_obstack, result);
obstack_ptr_grow (&joined_conditions_obstack, cond1);
obstack_ptr_grow (&joined_conditions_obstack, cond2);
- entry = XOBFINISH (&joined_conditions_obstack, const void **);
+ entry = XOBFINISH (&joined_conditions_obstack, const void *);
*htab_find_slot (joined_conditions, entry, INSERT) = entry;
return result;
}
@@ -512,7 +512,7 @@ read_quoted_string (void)
}
obstack_1grow (&string_obstack, 0);
- return XOBFINISH (&string_obstack, char *);
+ return XOBFINISH (&string_obstack, char);
}
/* Read a braced string (a la Tcl) onto the string obstack. Caller
@@ -549,7 +549,7 @@ read_braced_string (void)
}
obstack_1grow (&string_obstack, 0);
- return XOBFINISH (&string_obstack, char *);
+ return XOBFINISH (&string_obstack, char);
}
/* Read some kind of string constant. This is the high-level routine
=== modified file 'gcc/read-rtl.c'
--- gcc/read-rtl.c 2012-06-18 10:43:03 +0000
+++ gcc/read-rtl.c 2012-08-18 13:41:34 +0000
@@ -263,7 +263,7 @@ apply_iterator_to_string (const char *st
if (base != copy)
{
obstack_grow (&string_obstack, base, strlen (base) + 1);
- copy = XOBFINISH (&string_obstack, char *);
+ copy = XOBFINISH (&string_obstack, char);
copy_md_ptr_loc (copy, string);
return copy;
}
@@ -723,7 +723,7 @@ record_potential_iterator_use (struct it
/* Copy the attribute string into permanent storage, without the
angle brackets around it. */
obstack_grow0 (&string_obstack, name + 1, len - 2);
- record_attribute_use (group, ptr, XOBFINISH (&string_obstack, char *));
+ record_attribute_use (group, ptr, XOBFINISH (&string_obstack, char));
}
else
{
@@ -1028,7 +1028,7 @@ read_rtx_code (const char *code_name)
obstack_grow (&string_obstack, fn, strlen (fn));
sprintf (line_name, ":%d", read_md_lineno);
obstack_grow (&string_obstack, line_name, strlen (line_name)+1);
- stringbuf = XOBFINISH (&string_obstack, char *);
+ stringbuf = XOBFINISH (&string_obstack, char);
}
if (star_if_braced)
=== modified file 'gcc/tlink.c'
--- gcc/tlink.c 2012-05-31 20:19:00 +0000
+++ gcc/tlink.c 2012-08-18 13:47:18 +0000
@@ -319,7 +319,7 @@ obstack_fgets (FILE *stream, struct obst
if (obstack_object_size (ob) == 0)
return NULL;
obstack_1grow (ob, '\0');
- return XOBFINISH (ob, char *);
+ return XOBFINISH (ob, char);
}
static char *
@@ -542,7 +542,7 @@ recompile_files (void)
done:
obstack_ptr_grow (&temporary_obstack, f->main);
obstack_ptr_grow (&temporary_obstack, NULL);
- argv = XOBFINISH (&temporary_obstack, char **);
+ argv = XOBFINISH (&temporary_obstack, char *);
if (tlink_verbose)
fprintf (stderr, _("collect: recompiling %s\n"), f->main);
=== modified file 'gcc/tree-sra.c'
--- gcc/tree-sra.c 2012-08-17 07:51:31 +0000
+++ gcc/tree-sra.c 2012-08-18 13:48:12 +0000
@@ -1416,7 +1416,7 @@ make_fancy_name (tree expr)
{
make_fancy_name_1 (expr);
obstack_1grow (&name_obstack, '\0');
- return XOBFINISH (&name_obstack, char *);
+ return XOBFINISH (&name_obstack, char);
}
/* Construct a MEM_REF that would reference a part of aggregate BASE of type
=== modified file 'include/libiberty.h'
--- include/libiberty.h 2011-09-28 19:04:30 +0000
+++ include/libiberty.h 2012-08-18 13:33:45 +0000
@@ -361,12 +361,27 @@ extern unsigned int xcrc32 (const unsign
#define XDUPVAR(T, P, S1, S2) ((T *) xmemdup ((P), (S1), (S2)))
#define XRESIZEVAR(T, P, S) ((T *) xrealloc ((P), (S)))
-/* Type-safe obstack allocator. */
+/* Type-safe obstack allocator. You must first initialize the obstack.
+ T: Type, O: Obstack, N: Number of elements, S: Size in bytes,
+ P: Pointer to element. */
#define XOBNEW(O, T) ((T *) obstack_alloc ((O), sizeof (T)))
#define XOBNEWVEC(O, T, N) ((T *) obstack_alloc ((O), sizeof (T) * (N)))
#define XOBNEWVAR(O, T, S) ((T *) obstack_alloc ((O), (S)))
-#define XOBFINISH(O, T) ((T) obstack_finish ((O)))
+#define XOBDELETE(O, P) (obstack_free ((O), (P)))
+
+/* The following is for growing/shrinking objects in an obstack (D: Data to
+ grow the object with). This is useful when you don't know the object size
+ in advance, so you can't use obstack_alloc() You must finalise it with
+ obstack_finish() before actually using it.
+
+ See http://gcc.gnu.org/onlinedocs/libiberty/Growing-Objects.html */
+
+#define XOBGROW(O, T, D) obstack_grow ((O), (D), sizeof (T))
+#define XOBGROWVEC(O, T, D, N) obstack_grow ((O), (D), sizeof (T) * (N))
+#define XOBSHRINK(O, T) obstack_blank ((O), -1 * sizeof (T))
+#define XOBSHRINKVEC(O, T, N) obstack_blank ((O), -1 * sizeof (T) * (N))
+#define XOBFINISH(O, T) ((T *) obstack_finish ((O)))
/* hex character manipulation routines */
=== modified file 'libcpp/files.c'
--- libcpp/files.c 2012-04-30 16:57:22 +0000
+++ libcpp/files.c 2012-08-18 14:52:41 +0000
@@ -1210,9 +1210,7 @@ _cpp_init_files (cpp_reader *pfile)
pfile->nonexistent_file_hash = htab_create_alloc (127, htab_hash_string,
nonexistent_file_hash_eq,
NULL, xcalloc, free);
- _obstack_begin (&pfile->nonexistent_file_ob, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
+ obstack_init (&pfile->nonexistent_file_ob);
}
/* Finalize everything in this source file. */
=== modified file 'libcpp/identifiers.c'
--- libcpp/identifiers.c 2012-08-15 01:56:07 +0000
+++ libcpp/identifiers.c 2012-08-18 14:22:22 +0000
@@ -55,9 +55,7 @@ _cpp_init_hashtable (cpp_reader *pfile,
table = ht_create (13); /* 8K (=2^13) entries. */
table->alloc_node = alloc_node;
- _obstack_begin (&pfile->hash_ob, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
+ obstack_init (&pfile->hash_ob);
}
table->pfile = pfile;
=== modified file 'libcpp/include/symtab.h'
--- libcpp/include/symtab.h 2012-08-15 01:56:07 +0000
+++ libcpp/include/symtab.h 2012-08-18 15:07:01 +0000
@@ -21,6 +21,11 @@ along with this program; see the file CO
#include "obstack.h"
+#ifndef obstack_chunk_alloc
+ #define obstack_chunk_alloc (void *(*) (long)) xmalloc
+ #define obstack_chunk_free (void (*) (void *)) free
+#endif
+
#ifndef GTY
#define GTY(x) /* nothing */
#endif
=== modified file 'libcpp/init.c'
--- libcpp/init.c 2012-08-15 01:56:07 +0000
+++ libcpp/init.c 2012-08-18 14:27:50 +0000
@@ -242,9 +242,7 @@ cpp_create_reader (enum c_lang lang, cpp
_cpp_expand_op_stack (pfile);
/* Initialize the buffer obstack. */
- _obstack_begin (&pfile->buffer_ob, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
+ obstack_init (&pfile->buffer_ob);
_cpp_init_files (pfile);
=== modified file 'libcpp/internal.h'
--- libcpp/internal.h 2012-08-15 01:56:07 +0000
+++ libcpp/internal.h 2012-08-18 15:05:59 +0000
@@ -51,6 +51,12 @@ struct cset_converter
int width;
};
+#ifndef obstack_chunk_alloc
+ /* Needed for calling obstack_init(). */
+ #define obstack_chunk_alloc (void *(*) (long)) xmalloc
+ #define obstack_chunk_free (void (*) (void *)) free
+#endif
+
#define BITS_PER_CPPCHAR_T (CHAR_BIT * sizeof (cppchar_t))
/* Test if a sign is valid within a preprocessing number. */
=== modified file 'libcpp/symtab.c'
--- libcpp/symtab.c 2012-08-15 01:56:07 +0000
+++ libcpp/symtab.c 2012-08-18 15:06:27 +0000
@@ -62,9 +62,7 @@ ht_create (unsigned int order)
table = XCNEW (cpp_hash_table);
/* Strings need no alignment. */
- _obstack_begin (&table->stack, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
+ obstack_init (&table->stack);
obstack_alignment_mask (&table->stack) = 0;
^ permalink raw reply [flat|nested] 24+ messages in thread
* [graphds.h] Allocate graph from obstack
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
2012-08-18 11:50 ` Dimitrios Apostolou
2012-08-18 16:37 ` Dimitrios Apostolou
@ 2012-08-18 18:10 ` Dimitrios Apostolou
2012-08-19 16:55 ` Richard Guenther
2012-08-18 19:10 ` more malloc mitigation Dimitrios Apostolou
` (5 subsequent siblings)
8 siblings, 1 reply; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-18 18:10 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 540 bytes --]
Initially I had one obstack per struct graph, which was better than using
XNEW for every edge, but still obstack_init() called from new_graph() was
too frequent.
So in this iteration of the patch the obstack is static global,
initialised once and never freed. Please advise on whether this is
acceptable, and also where I should initialise the obstack once, and avoid
checking if it's NULL in every use.
Minor speed gains (couple of ms), tested with pre-C++ conversion snapshot,
I'll retest soon and post update.
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/plain, Size: 16769 bytes --]
2012-08-18 Dimitrios Apostolou <jimis@gmx.net>
* gcc/graphds.h: Guarded the header file. Included libiberty.h and
obstack.h.
(graph_obstack): New static obstack to allocate graphs and
graph_edges from.
(new_graph, add_edge): Add obstack argument.
(free_graph): Remove.
* gcc/graphds.c (new_graph): Allocate graph, vertices from obstack.
(add_edge): Allocate edge from obstack.
(free_graph): Remove, all graph data is now freed when freeing the
object in the obstack.
* gcc/tree-data-ref.h (free_rdg): Same.
(build_empty_rdg): Add obstack argument.
* gcc/cfgloopanal.c (mark_irreducible_loops): Initialise obstack
if it's not, use it for graph allocations.
* gcc/dominance.c (iterate_fix_dominators): Same.
* gcc/graphite-sese-to-poly.c (build_alias_set_optimal_p)
(build_base_obj_set_for_drs): Same.
* gcc/tree-data-ref.c (rdg_vertex_for_stmt)
(create_rdg_edge_for_ddr, create_rdg_edges_for_scalar)
(create_rdg_edges, create_rdg_vertices)
(known_dependences_p,build_empty_rdg, build_rdg, free_rdg): Same.
* gcc/tree-loop-distribution.c (distribute_loop): Same.
=== modified file 'gcc/cfgloopanal.c'
--- gcc/cfgloopanal.c 2012-05-31 20:19:00 +0000
+++ gcc/cfgloopanal.c 2012-08-18 16:43:02 +0000
@@ -93,8 +93,14 @@ mark_irreducible_loops (void)
e->flags &= ~EDGE_IRREDUCIBLE_LOOP;
}
+ if (graph_obstack == NULL)
+ {
+ graph_obstack = XNEW (struct obstack);
+ obstack_init (graph_obstack);
+ }
+
/* Create the edge lists. */
- g = new_graph (last_basic_block + num);
+ g = new_graph (last_basic_block + num, graph_obstack);
FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
FOR_EACH_EDGE (e, ei, act->succs)
@@ -134,7 +140,7 @@ mark_irreducible_loops (void)
src = LOOP_REPR (cloop);
}
- add_edge (g, src, dest)->data = e;
+ add_edge (g, src, dest, graph_obstack)->data = e;
}
/* Find the strongly connected components. */
@@ -161,7 +167,8 @@ mark_irreducible_loops (void)
real->src->flags |= BB_IRREDUCIBLE_LOOP;
}
- free_graph (g);
+ /* Destroy all data allocated for the graph. */
+ XOBDELETE (graph_obstack, g);
loops_state_set (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS);
return irred_loop_found;
=== modified file 'gcc/dominance.c'
--- gcc/dominance.c 2012-08-14 15:59:41 +0000
+++ gcc/dominance.c 2012-08-18 16:43:02 +0000
@@ -1341,7 +1341,13 @@ iterate_fix_dominators (enum cdi_directi
}
*pointer_map_insert (map, ENTRY_BLOCK_PTR) = (void *) (size_t) n;
- g = new_graph (n + 1);
+ if (graph_obstack == NULL)
+ {
+ graph_obstack = XNEW (struct obstack);
+ obstack_init (graph_obstack);
+ }
+
+ g = new_graph (n + 1, graph_obstack);
for (y = 0; y < g->n_vertices; y++)
g->vertices[y].data = BITMAP_ALLOC (NULL);
FOR_EACH_VEC_ELT (basic_block, bbs, i, bb)
@@ -1358,7 +1364,7 @@ iterate_fix_dominators (enum cdi_directi
if (!bitmap_set_bit ((bitmap) g->vertices[dom_i].data, i))
continue;
- add_edge (g, dom_i, i);
+ add_edge (g, dom_i, i, graph_obstack);
}
}
for (y = 0; y < g->n_vertices; y++)
@@ -1392,7 +1398,8 @@ iterate_fix_dominators (enum cdi_directi
free (brother);
free (parent);
- free_graph (g);
+ /* Destroy all data allocated for the graph. */
+ XOBDELETE (graph_obstack, g);
}
void
=== modified file 'gcc/graphds.c'
--- gcc/graphds.c 2009-11-25 10:55:54 +0000
+++ gcc/graphds.c 2012-08-18 16:43:02 +0000
@@ -53,28 +53,29 @@ dump_graph (FILE *f, struct graph *g)
}
}
-/* Creates a new graph with N_VERTICES vertices. */
+/* Creates a new graph with N_VERTICES vertices from obstack O. */
struct graph *
-new_graph (int n_vertices)
+new_graph (int n_vertices, struct obstack *o)
{
- struct graph *g = XNEW (struct graph);
+ struct graph *g = XOBNEW (o, struct graph);
g->n_vertices = n_vertices;
- g->vertices = XCNEWVEC (struct vertex, n_vertices);
+ g->vertices = XOBNEWVEC (o, struct vertex, n_vertices);
+ memset (g->vertices, 0, n_vertices * sizeof (*g->vertices));
return g;
}
-/* Adds an edge from F to T to graph G. The new edge is returned. */
+/* Adds an edge from F to T to graph G. Allocations are from obstack O. The
+ new edge is returned. */
struct graph_edge *
-add_edge (struct graph *g, int f, int t)
+add_edge (struct graph *g, int f, int t, struct obstack *o)
{
- struct graph_edge *e = XNEW (struct graph_edge);
+ struct graph_edge *e = XOBNEW (o, struct graph_edge);
struct vertex *vf = &g->vertices[f], *vt = &g->vertices[t];
-
e->src = f;
e->dest = t;
@@ -321,28 +322,6 @@ for_each_edge (struct graph *g, graphds_
callback (g, e);
}
-/* Releases the memory occupied by G. */
-
-void
-free_graph (struct graph *g)
-{
- struct graph_edge *e, *n;
- struct vertex *v;
- int i;
-
- for (i = 0; i < g->n_vertices; i++)
- {
- v = &g->vertices[i];
- for (e = v->succ; e; e = n)
- {
- n = e->succ_next;
- free (e);
- }
- }
- free (g->vertices);
- free (g);
-}
-
/* Returns the nearest common ancestor of X and Y in tree whose parent
links are given by PARENT. MARKS is the array used to mark the
vertices of the tree, and MARK is the number currently used as a mark. */
=== modified file 'gcc/graphds.h'
--- gcc/graphds.h 2009-02-20 15:20:38 +0000
+++ gcc/graphds.h 2012-08-18 17:18:30 +0000
@@ -18,6 +18,11 @@ You should have received a copy of the G
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#ifndef GRAPHDS_H
+#define GRAPHDS_H
+
+#include "obstack.h"
+
/* Structure representing edge of a graph. */
struct graph_edge
@@ -28,6 +33,8 @@ struct graph_edge
void *data; /* Data attached to the edge. */
};
+static struct obstack *graph_obstack ATTRIBUTE_UNUSED;
+
/* Structure representing vertex of a graph. */
struct vertex
@@ -50,9 +57,9 @@ struct graph
htab_t indices; /* Fast lookup for indices. */
};
-struct graph *new_graph (int);
+struct graph *new_graph (int, struct obstack *);
void dump_graph (FILE *, struct graph *);
-struct graph_edge *add_edge (struct graph *, int, int);
+struct graph_edge *add_edge (struct graph *, int, int, struct obstack *);
void identify_vertices (struct graph *, int, int);
int graphds_dfs (struct graph *, int *, int,
VEC (int, heap) **, bool, bitmap);
@@ -60,4 +67,5 @@ int graphds_scc (struct graph *, bitmap)
void graphds_domtree (struct graph *, int, int *, int *, int *);
typedef void (*graphds_edge_callback) (struct graph *, struct graph_edge *);
void for_each_edge (struct graph *, graphds_edge_callback);
-void free_graph (struct graph *g);
+
+#endif /* GRAPHDS_H */
=== modified file 'gcc/graphite-sese-to-poly.c'
--- gcc/graphite-sese-to-poly.c 2012-08-16 14:27:51 +0000
+++ gcc/graphite-sese-to-poly.c 2012-08-18 16:43:02 +0000
@@ -1719,7 +1719,7 @@ static int
build_alias_set_optimal_p (VEC (data_reference_p, heap) *drs)
{
int num_vertices = VEC_length (data_reference_p, drs);
- struct graph *g = new_graph (num_vertices);
+ struct graph *g;
data_reference_p dr1, dr2;
int i, j;
int num_connected_components;
@@ -1730,12 +1730,19 @@ build_alias_set_optimal_p (VEC (data_ref
int this_component_is_clique;
int all_components_are_cliques = 1;
+ if (graph_obstack == NULL)
+ {
+ graph_obstack = XNEW (struct obstack);
+ obstack_init (graph_obstack);
+ }
+ g = new_graph (num_vertices, graph_obstack);
+
FOR_EACH_VEC_ELT (data_reference_p, drs, i, dr1)
for (j = i+1; VEC_iterate (data_reference_p, drs, j, dr2); j++)
if (dr_may_alias_p (dr1, dr2, true))
{
- add_edge (g, i, j);
- add_edge (g, j, i);
+ add_edge (g, i, j, graph_obstack);
+ add_edge (g, j, i, graph_obstack);
}
all_vertices = XNEWVEC (int, num_vertices);
@@ -1795,7 +1802,7 @@ build_alias_set_optimal_p (VEC (data_ref
free (all_vertices);
free (vertices);
- free_graph (g);
+ XOBDELETE (graph_obstack, g);
return all_components_are_cliques;
}
@@ -1805,17 +1812,24 @@ static void
build_base_obj_set_for_drs (VEC (data_reference_p, heap) *drs)
{
int num_vertex = VEC_length (data_reference_p, drs);
- struct graph *g = new_graph (num_vertex);
+ struct graph *g;
data_reference_p dr1, dr2;
int i, j;
int *queue;
+ if (graph_obstack == NULL)
+ {
+ graph_obstack = XNEW (struct obstack);
+ obstack_init (graph_obstack);
+ }
+ g = new_graph (num_vertex, graph_obstack);
+
FOR_EACH_VEC_ELT (data_reference_p, drs, i, dr1)
for (j = i + 1; VEC_iterate (data_reference_p, drs, j, dr2); j++)
if (dr_same_base_object_p (dr1, dr2))
{
- add_edge (g, i, j);
- add_edge (g, j, i);
+ add_edge (g, i, j, graph_obstack);
+ add_edge (g, j, i, graph_obstack);
}
queue = XNEWVEC (int, num_vertex);
@@ -1836,7 +1850,7 @@ build_base_obj_set_for_drs (VEC (data_re
}
free (queue);
- free_graph (g);
+ XOBDELETE (graph_obstack, g);
}
/* Build the data references for PBB. */
=== modified file 'gcc/tree-data-ref.c'
--- gcc/tree-data-ref.c 2012-07-16 11:32:42 +0000
+++ gcc/tree-data-ref.c 2012-08-18 16:43:02 +0000
@@ -4936,10 +4936,10 @@ rdg_vertex_for_stmt (struct graph *rdg A
/* Creates an edge in RDG for each distance vector from DDR. The
order that we keep track of in the RDG is the order in which
- statements have to be executed. */
+ statements have to be executed. Allocation happen from obstack O. */
static void
-create_rdg_edge_for_ddr (struct graph *rdg, ddr_p ddr)
+create_rdg_edge_for_ddr (struct graph *rdg, ddr_p ddr, struct obstack *o)
{
struct graph_edge *e;
int va, vb;
@@ -4963,8 +4963,8 @@ create_rdg_edge_for_ddr (struct graph *r
if (va < 0 || vb < 0)
return;
- e = add_edge (rdg, va, vb);
- e->data = XNEW (struct rdg_edge);
+ e = add_edge (rdg, va, vb, o);
+ e->data = XOBNEW (o, struct rdg_edge);
RDGE_LEVEL (e) = level;
RDGE_RELATION (e) = ddr;
@@ -4981,10 +4981,11 @@ create_rdg_edge_for_ddr (struct graph *r
}
/* Creates dependence edges in RDG for all the uses of DEF. IDEF is
- the index of DEF in RDG. */
+ the index of DEF in RDG. Allocation happen from obstack O. */
static void
-create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef)
+create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef,
+ struct obstack *o)
{
use_operand_p imm_use_p;
imm_use_iterator iterator;
@@ -4997,17 +4998,18 @@ create_rdg_edges_for_scalar (struct grap
if (use < 0)
continue;
- e = add_edge (rdg, idef, use);
- e->data = XNEW (struct rdg_edge);
+ e = add_edge (rdg, idef, use, o);
+ e->data = XOBNEW (o, struct rdg_edge);
RDGE_TYPE (e) = flow_dd;
RDGE_RELATION (e) = NULL;
}
}
-/* Creates the edges of the reduced dependence graph RDG. */
+/* Creates the edges of the reduced dependence graph RDG. Allocations happen
+ from obstack O. */
static void
-create_rdg_edges (struct graph *rdg, VEC (ddr_p, heap) *ddrs)
+create_rdg_edges (struct graph *rdg, VEC (ddr_p, heap) *ddrs, struct obstack *o)
{
int i;
struct data_dependence_relation *ddr;
@@ -5016,18 +5018,20 @@ create_rdg_edges (struct graph *rdg, VEC
FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr)
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
- create_rdg_edge_for_ddr (rdg, ddr);
+ create_rdg_edge_for_ddr (rdg, ddr, o);
for (i = 0; i < rdg->n_vertices; i++)
FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i),
iter, SSA_OP_DEF)
- create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i);
+ create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i, o);
}
-/* Build the vertices of the reduced dependence graph RDG. */
+/* Build the vertices of the reduced dependence graph RDG. Data is allocated
+ from obstack O. */
static void
-create_rdg_vertices (struct graph *rdg, VEC (gimple, heap) *stmts, loop_p loop)
+create_rdg_vertices (struct graph *rdg, VEC (gimple, heap) *stmts, loop_p loop,
+ struct obstack *o)
{
int i, j;
gimple stmt;
@@ -5041,7 +5045,7 @@ create_rdg_vertices (struct graph *rdg,
/* Record statement to vertex mapping. */
gimple_set_uid (stmt, i);
- v->data = XNEW (struct rdg_vertex);
+ v->data = XOBNEW (o, struct rdg_vertex);
RDGV_STMT (v) = stmt;
RDGV_DATAREFS (v) = NULL;
RDGV_HAS_MEM_WRITE (v) = false;
@@ -5115,24 +5119,30 @@ known_dependences_p (VEC (ddr_p, heap) *
/* Build the Reduced Dependence Graph (RDG) with one vertex per
statement of the loop nest, and one edge per data dependence or
- scalar dependence. */
+ scalar dependence. Allocated from obstack O. */
struct graph *
-build_empty_rdg (int n_stmts)
+build_empty_rdg (int n_stmts, struct obstack *o)
{
- struct graph *rdg = new_graph (n_stmts);
- return rdg;
+ if (graph_obstack == NULL)
+ {
+ graph_obstack = XOBNEW (o, struct obstack);
+ obstack_init (graph_obstack);
+ }
+
+ return new_graph (n_stmts, o);
}
/* Build the Reduced Dependence Graph (RDG) with one vertex per
statement of the loop nest, and one edge per data dependence or
- scalar dependence. */
+ scalar dependence. All data is allocated from obstack O. */
struct graph *
build_rdg (struct loop *loop,
VEC (loop_p, heap) **loop_nest,
VEC (ddr_p, heap) **dependence_relations,
- VEC (data_reference_p, heap) **datarefs)
+ VEC (data_reference_p, heap) **datarefs,
+ struct obstack *o)
{
struct graph *rdg = NULL;
@@ -5142,38 +5152,15 @@ build_rdg (struct loop *loop,
{
VEC (gimple, heap) *stmts = VEC_alloc (gimple, heap, 10);
stmts_from_loop (loop, &stmts);
- rdg = build_empty_rdg (VEC_length (gimple, stmts));
- create_rdg_vertices (rdg, stmts, loop);
- create_rdg_edges (rdg, *dependence_relations);
+ rdg = build_empty_rdg (VEC_length (gimple, stmts), o);
+ create_rdg_vertices (rdg, stmts, loop, o);
+ create_rdg_edges (rdg, *dependence_relations, o);
VEC_free (gimple, heap, stmts);
}
return rdg;
}
-/* Free the reduced dependence graph RDG. */
-
-void
-free_rdg (struct graph *rdg)
-{
- int i;
-
- for (i = 0; i < rdg->n_vertices; i++)
- {
- struct vertex *v = &(rdg->vertices[i]);
- struct graph_edge *e;
-
- for (e = v->succ; e; e = e->succ_next)
- free (e->data);
-
- gimple_set_uid (RDGV_STMT (v), -1);
- free_data_refs (RDGV_DATAREFS (v));
- free (v->data);
- }
-
- free_graph (rdg);
-}
-
/* Determines whether the statement from vertex V of the RDG has a
definition used outside the loop that contains this statement. */
=== modified file 'gcc/tree-data-ref.h'
--- gcc/tree-data-ref.h 2012-06-06 09:45:27 +0000
+++ gcc/tree-data-ref.h 2012-08-18 16:43:02 +0000
@@ -589,9 +589,9 @@ typedef struct rdg_edge
struct graph *build_rdg (struct loop *,
VEC (loop_p, heap) **,
VEC (ddr_p, heap) **,
- VEC (data_reference_p, heap) **);
-struct graph *build_empty_rdg (int);
-void free_rdg (struct graph *);
+ VEC (data_reference_p, heap) **,
+ struct obstack *);
+struct graph *build_empty_rdg (int, struct obstack *);
/* Return the index of the variable VAR in the LOOP_NEST array. */
=== modified file 'gcc/tree-loop-distribution.c'
--- gcc/tree-loop-distribution.c 2012-08-14 14:16:18 +0000
+++ gcc/tree-loop-distribution.c 2012-08-18 16:43:02 +0000
@@ -1393,7 +1393,14 @@ distribute_loop (struct loop *loop, VEC
datarefs = VEC_alloc (data_reference_p, heap, 10);
dependence_relations = VEC_alloc (ddr_p, heap, 100);
loop_nest = VEC_alloc (loop_p, heap, 3);
- rdg = build_rdg (loop, &loop_nest, &dependence_relations, &datarefs);
+
+ if (graph_obstack == NULL)
+ {
+ graph_obstack = XNEW (struct obstack);
+ obstack_init (graph_obstack);
+ }
+ rdg = build_rdg (loop, &loop_nest, &dependence_relations, &datarefs,
+ graph_obstack);
if (!rdg)
{
@@ -1429,7 +1436,9 @@ distribute_loop (struct loop *loop, VEC
res = ldist_gen (loop, rdg, vertices);
VEC_free (int, heap, vertices);
- free_rdg (rdg);
+
+ XOBDELETE (graph_obstack, rdg);
+
free_dependence_relations (dependence_relations);
free_data_refs (datarefs);
VEC_free (loop_p, heap, loop_nest);
^ permalink raw reply [flat|nested] 24+ messages in thread
* more malloc mitigation
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
` (2 preceding siblings ...)
2012-08-18 18:10 ` [graphds.h] Allocate graph from obstack Dimitrios Apostolou
@ 2012-08-18 19:10 ` Dimitrios Apostolou
2012-08-19 18:30 ` alloc_pool for tree-ssa-pre.c:phi_translate_table Dimitrios Apostolou
` (4 subsequent siblings)
8 siblings, 0 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-18 19:10 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 900 bytes --]
Hi,
2012-08-18 Dimitrios Apostolou <jimis@gmx.net>
* gcc/tree-ssa-sccvn.c (struct vn_tables_s): Add obstack_start to
mark the first allocated object on the obstack.
(process_scc, allocate_vn_table): Use it.
(init_scc_vn): Don't truncate shared_lookup_references vector.
(prealloc_ref_ops_vec): New static vector.
(create_reference_ops_from_ref, create_reference_ops_from_call):
Use it instead of locally allocated one.
(free_scc_vn): Truncate vectors to 0, but keep them most 16 slots
long.
I'd have used a stack vector for create_reference_ops_from_{ref,call}
instead of a static one on the heap, but the functions return heap
vectors. Can I just cast a stack vector to a heap one?
Also is it acceptable to leak 4K because of never freeing the whole
obstack?
Tested on x86 with old snapshot, will post update soon after testing with
more recent one.
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/plain, Size: 4637 bytes --]
2012-08-18 Dimitrios Apostolou <jimis@gmx.net>
* gcc/tree-ssa-sccvn.c (struct vn_tables_s): Add obstack_start to
mark the first allocated object on the obstack.
(process_scc, allocate_vn_table): Use it.
(init_scc_vn): Don't truncate shared_lookup_references vector.
(prealloc_ref_ops_vec): New static vector.
(create_reference_ops_from_ref, create_reference_ops_from_call):
Use it instead of locally allocated one.
(free_scc_vn): Truncate vectors to 0, but keep them most 16 slots
long.
=== modified file 'gcc/tree-ssa-sccvn.c'
--- gcc/tree-ssa-sccvn.c 2012-08-16 14:27:51 +0000
+++ gcc/tree-ssa-sccvn.c 2012-08-18 16:43:02 +0000
@@ -105,6 +105,7 @@ typedef struct vn_tables_s
htab_t phis;
htab_t references;
struct obstack nary_obstack;
+ long *obstack_start;
alloc_pool phis_pool;
alloc_pool references_pool;
} *vn_tables_t;
@@ -973,16 +974,21 @@ copy_reference_ops_from_call (gimple cal
}
}
+/* Preallocated vector with sufficient space - see free_scc_vn(). Helps to
+ avoid reallocations and space, since when we VEC_copy() it, only its exact
+ length is duplicated. */
+
+static VEC(vn_reference_op_s, heap) *prealloc_ref_ops_vec;
+
/* Create a vector of vn_reference_op_s structures from REF, a
- REFERENCE_CLASS_P tree. The vector is not shared. */
+ REFERENCE_CLASS_P tree. The vector is not shared. */
static VEC(vn_reference_op_s, heap) *
create_reference_ops_from_ref (tree ref)
{
- VEC (vn_reference_op_s, heap) *result = NULL;
-
- copy_reference_ops_from_ref (ref, &result);
- return result;
+ VEC_truncate (vn_reference_op_s, prealloc_ref_ops_vec, 0);
+ copy_reference_ops_from_ref (ref, &prealloc_ref_ops_vec);
+ return VEC_copy (vn_reference_op_s, heap, prealloc_ref_ops_vec);
}
/* Create a vector of vn_reference_op_s structures from CALL, a
@@ -991,10 +997,9 @@ create_reference_ops_from_ref (tree ref)
static VEC(vn_reference_op_s, heap) *
create_reference_ops_from_call (gimple call)
{
- VEC (vn_reference_op_s, heap) *result = NULL;
-
- copy_reference_ops_from_call (call, &result);
- return result;
+ VEC_truncate (vn_reference_op_s, prealloc_ref_ops_vec, 0);
+ copy_reference_ops_from_call (call, &prealloc_ref_ops_vec);
+ return VEC_copy (vn_reference_op_s, heap, prealloc_ref_ops_vec);
}
/* Fold *& at position *I_P in a vn_reference_op_s vector *OPS. Updates
@@ -3610,8 +3615,9 @@ process_scc (VEC (tree, heap) *scc)
htab_empty (optimistic_info->nary);
htab_empty (optimistic_info->phis);
htab_empty (optimistic_info->references);
- obstack_free (&optimistic_info->nary_obstack, NULL);
- gcc_obstack_init (&optimistic_info->nary_obstack);
+ /* Quick way to empty the obstack but keep it ready for reuse. */
+ obstack_free (&optimistic_info->nary_obstack,
+ optimistic_info->obstack_start);
empty_alloc_pool (optimistic_info->phis_pool);
empty_alloc_pool (optimistic_info->references_pool);
FOR_EACH_VEC_ELT (tree, scc, i, var)
@@ -3796,6 +3802,7 @@ allocate_vn_table (vn_tables_t table)
free_reference);
gcc_obstack_init (&table->nary_obstack);
+ table->obstack_start = XOBNEW (&table->nary_obstack, long);
table->phis_pool = create_alloc_pool ("VN phis",
sizeof (struct vn_phi_s),
30);
@@ -3842,7 +3849,6 @@ init_scc_vn (void)
gcc_obstack_init (&vn_ssa_aux_obstack);
shared_lookup_phiargs = NULL;
- shared_lookup_references = NULL;
rpo_numbers = XNEWVEC (int, last_basic_block);
rpo_numbers_temp = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
pre_and_rev_post_order_compute (NULL, rpo_numbers_temp, false);
@@ -3887,9 +3893,19 @@ free_scc_vn (void)
htab_delete (constant_to_value_id);
BITMAP_FREE (constant_value_ids);
VEC_free (tree, heap, shared_lookup_phiargs);
- VEC_free (vn_reference_op_s, heap, shared_lookup_references);
XDELETEVEC (rpo_numbers);
+ /* Keep the shared_lookup_references and prealloc_ref_ops_vec vectors with
+ at most 16 slots. */
+ VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
+ if (VEC_space (vn_reference_op_s, shared_lookup_references, 17))
+ VEC_reserve_exact (vn_reference_op_s, heap,
+ shared_lookup_references, 16);
+ VEC_truncate (vn_reference_op_s, prealloc_ref_ops_vec, 0);
+ if (VEC_space (vn_reference_op_s, prealloc_ref_ops_vec, 17))
+ VEC_reserve_exact (vn_reference_op_s, heap,
+ prealloc_ref_ops_vec, 16);
+
for (i = 0; i < num_ssa_names; i++)
{
tree name = ssa_name (i);
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [graphds.h] Allocate graph from obstack
2012-08-18 18:10 ` [graphds.h] Allocate graph from obstack Dimitrios Apostolou
@ 2012-08-19 16:55 ` Richard Guenther
2012-08-20 12:04 ` Paolo Bonzini
0 siblings, 1 reply; 24+ messages in thread
From: Richard Guenther @ 2012-08-19 16:55 UTC (permalink / raw)
To: Dimitrios Apostolou; +Cc: gcc-patches, Andrey Belevantsev
On Sat, Aug 18, 2012 at 8:10 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
> Initially I had one obstack per struct graph, which was better than using
> XNEW for every edge, but still obstack_init() called from new_graph() was
> too frequent.
>
> So in this iteration of the patch the obstack is static global, initialised
> once and never freed. Please advise on whether this is acceptable, and also
> where I should initialise the obstack once, and avoid checking if it's NULL
> in every use.
>
> Minor speed gains (couple of ms), tested with pre-C++ conversion snapshot,
> I'll retest soon and post update.
Either an obstack per graph or the ability to specify an obstack for allocation.
A global obstack with global lifetime is bad IMHO.
Richard.
>
> Thanks,
> Dimitris
^ permalink raw reply [flat|nested] 24+ messages in thread
* alloc_pool for tree-ssa-pre.c:phi_translate_table
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
` (3 preceding siblings ...)
2012-08-18 19:10 ` more malloc mitigation Dimitrios Apostolou
@ 2012-08-19 18:30 ` Dimitrios Apostolou
2012-08-20 7:38 ` Richard Guenther
2012-08-19 18:30 ` obstack for equiv_class_label, more vectors on stack Dimitrios Apostolou
` (3 subsequent siblings)
8 siblings, 1 reply; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-19 18:30 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 506 bytes --]
2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
* gcc/tree-ssa-pre.c (phi_translate_pool): New static global
alloc_pool, used for allocating struct expr_pred_trans_d for
phi_translate_table.
(phi_trans_add, init_pre, fini_pre): Use it, avoids thousand of
malloc() and free() calls.
This avoids lots of malloc/free calls and slow iterations during numerous
htab_delete() in fini_pre(). Tested on pre C++-snapshot, will update info
as soon as a post C++ one is available.
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/PLAIN, Size: 2508 bytes --]
2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
* gcc/tree-ssa-pre.c (phi_translate_pool): New static global
alloc_pool, used for allocating struct expr_pred_trans_d for
phi_translate_table.
(phi_trans_add, init_pre, fini_pre): Use it, avoids thousand of
malloc() and free() calls.
=== modified file 'gcc/tree-ssa-pre.c'
--- gcc/tree-ssa-pre.c 2012-08-17 08:03:54 +0000
+++ gcc/tree-ssa-pre.c 2012-08-18 16:43:02 +0000
@@ -486,7 +486,7 @@ static bitmap need_ab_cleanup;
/* A three tuple {e, pred, v} used to cache phi translations in the
phi_translate_table. */
-typedef struct expr_pred_trans_d : typed_free_remove<expr_pred_trans_d>
+typedef struct expr_pred_trans_d : typed_noop_remove<expr_pred_trans_d>
{
/* The expression. */
pre_expr e;
@@ -508,6 +508,12 @@ typedef struct expr_pred_trans_d : typed
} *expr_pred_trans_t;
typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
+/* Pool of memory for the above */
+
+static alloc_pool phi_translate_pool;
+
+/* Return the hash value for a phi translation table entry. */
+
inline hashval_t
expr_pred_trans_d::hash (const expr_pred_trans_d *e)
{
@@ -561,7 +567,8 @@ static inline void
phi_trans_add (pre_expr e, pre_expr v, basic_block pred)
{
expr_pred_trans_t *slot;
- expr_pred_trans_t new_pair = XNEW (struct expr_pred_trans_d);
+ expr_pred_trans_t new_pair =
+ (expr_pred_trans_t) pool_alloc (phi_translate_pool);
new_pair->e = e;
new_pair->pred = pred;
new_pair->v = v;
@@ -570,7 +577,8 @@ phi_trans_add (pre_expr e, pre_expr v, b
slot = phi_translate_table.find_slot_with_hash (new_pair,
new_pair->hashcode, INSERT);
- free (*slot);
+ if (*slot)
+ pool_free (phi_translate_pool, *slot);
*slot = new_pair;
}
@@ -4798,6 +4806,9 @@ init_pre (bool do_fre)
calculate_dominance_info (CDI_DOMINATORS);
bitmap_obstack_initialize (&grand_bitmap_obstack);
+ phi_translate_pool = create_alloc_pool ("phi_translate_table",
+ sizeof (struct expr_pred_trans_d),
+ 512);
phi_translate_table.create (5110);
expression_to_id.create (num_ssa_names * 3);
bitmap_set_pool = create_alloc_pool ("Bitmap sets",
@@ -4832,6 +4843,7 @@ fini_pre (bool do_fre)
free_alloc_pool (bitmap_set_pool);
free_alloc_pool (pre_expr_pool);
phi_translate_table.dispose ();
+ free_alloc_pool (phi_translate_pool);
expression_to_id.dispose ();
VEC_free (unsigned, heap, name_to_id);
^ permalink raw reply [flat|nested] 24+ messages in thread
* obstack for equiv_class_label, more vectors on stack
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
` (4 preceding siblings ...)
2012-08-19 18:30 ` alloc_pool for tree-ssa-pre.c:phi_translate_table Dimitrios Apostolou
@ 2012-08-19 18:30 ` Dimitrios Apostolou
2012-08-19 18:31 ` enlarge hot allocation pools Dimitrios Apostolou
` (2 subsequent siblings)
8 siblings, 0 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-19 18:30 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1159 bytes --]
2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
* gcc/tree-ssa-structalias.c: Change declaration of ce_s type
vector from heap to stack. Update all relevant functions to
VEC_alloc() such vector upfront with enough (32) slots so that
malloc() calls are mostly avoided.
(equiv_class_obstack) New global static obstack for allocating
struct equiv_class_label.
(equiv_class_add): Use the above instead of malloc().
(perform_var_substitution): Don't allow entries of
location_equiv_class_table to be freed, because they are free'd...
(free_var_substitution_info): ...here by freeing the obstack.
* gcc/vecir.h: Add declaration of stack allocated tree type vector.
* gcc/tree-ssa-sccvn.c (vn_phi_insert, print_scc, compare_ops)
(sort_scc, copy_reference, extract_and_process_scc_for_name): Use
it, instead of heap allocated vector.
Not all of these places are hot on the profiler, but since I changed a few
I had to change them all to remove complete the heap ce_s vector. Passes
tests and offers small gains (couple of ms), but expect a more thorough
report and testing against a new snapshot by next week.
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/PLAIN, Size: 35122 bytes --]
2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
* gcc/tree-ssa-structalias.c: Change declaration of ce_s type
vector from heap to stack. Update all relevant functions to
VEC_alloc() such vector upfront with enough (32) slots so that
malloc() calls are mostly avoided.
(equiv_class_obstack) New global static obstack for allocating
struct equiv_class_label.
(equiv_class_add): Use the above instead of malloc().
(perform_var_substitution): Don't allow entries of
location_equiv_class_table to be freed, because they are free'd...
(free_var_substitution_info): ...here by freeing the obstack.
* gcc/vecir.h: Add declaration of stack allocated tree type vector.
* gcc/tree-ssa-sccvn.c (vn_phi_insert, print_scc, compare_ops)
(sort_scc, copy_reference, extract_and_process_scc_for_name): Use
it, instead of heap allocated vector.
=== modified file 'gcc/tree-ssa-structalias.c'
--- gcc/tree-ssa-structalias.c 2012-08-16 14:27:51 +0000
+++ gcc/tree-ssa-structalias.c 2012-08-18 16:43:02 +0000
@@ -472,11 +472,14 @@ struct constraint_expr
typedef struct constraint_expr ce_s;
DEF_VEC_O(ce_s);
-DEF_VEC_ALLOC_O(ce_s, heap);
-static void get_constraint_for_1 (tree, VEC(ce_s, heap) **, bool, bool);
-static void get_constraint_for (tree, VEC(ce_s, heap) **);
-static void get_constraint_for_rhs (tree, VEC(ce_s, heap) **);
-static void do_deref (VEC (ce_s, heap) **);
+DEF_VEC_ALLOC_O_STACK(ce_s);
+#define VEC_ce_s_stack_alloc(alloc) \
+ VEC_stack_alloc (ce_s, alloc)
+
+static void get_constraint_for_1 (tree, VEC(ce_s, stack) **, bool, bool);
+static void get_constraint_for (tree, VEC(ce_s, stack) **);
+static void get_constraint_for_rhs (tree, VEC(ce_s, stack) **);
+static void do_deref (VEC (ce_s, stack) **);
/* Our set constraints are made up of two constraint expressions, one
LHS, and one RHS.
@@ -1893,6 +1896,9 @@ static htab_t pointer_equiv_class_table;
classes. */
static htab_t location_equiv_class_table;
+/* Pool of memory for storing the above */
+static struct obstack equiv_class_obstack;
+
/* Hash function for a equiv_class_label_t */
static hashval_t
@@ -1942,7 +1948,7 @@ equiv_class_add (htab_t table, unsigned
bitmap labels)
{
void **slot;
- equiv_class_label_t ecl = XNEW (struct equiv_class_label);
+ equiv_class_label_t ecl = XOBNEW (&equiv_class_obstack, struct equiv_class_label);
ecl->labels = labels;
ecl->equivalence_class = equivalence_class;
@@ -2153,10 +2159,12 @@ perform_var_substitution (constraint_gra
struct scc_info *si = init_scc_info (size);
bitmap_obstack_initialize (&iteration_obstack);
+ gcc_obstack_init (&equiv_class_obstack);
+ /* NULL free function, we'll free the whole pool at the end of the pass. */
pointer_equiv_class_table = htab_create (511, equiv_class_label_hash,
- equiv_class_label_eq, free);
+ equiv_class_label_eq, NULL);
location_equiv_class_table = htab_create (511, equiv_class_label_hash,
- equiv_class_label_eq, free);
+ equiv_class_label_eq, NULL);
pointer_equiv_class = 1;
location_equiv_class = 1;
@@ -2263,6 +2271,7 @@ free_var_substitution_info (struct scc_i
sbitmap_free (graph->direct_nodes);
htab_delete (pointer_equiv_class_table);
htab_delete (location_equiv_class_table);
+ obstack_free (&equiv_class_obstack, NULL);
bitmap_obstack_release (&iteration_obstack);
}
@@ -2741,7 +2750,7 @@ new_scalar_tmp_constraint_exp (const cha
If address_p is true, the result will be taken its address of. */
static void
-get_constraint_for_ssa_var (tree t, VEC(ce_s, heap) **results, bool address_p)
+get_constraint_for_ssa_var (tree t, VEC(ce_s, stack) **results, bool address_p)
{
struct constraint_expr cexpr;
varinfo_t vi;
@@ -2793,12 +2802,12 @@ get_constraint_for_ssa_var (tree t, VEC(
for (; vi; vi = vi->next)
{
cexpr.var = vi->id;
- VEC_safe_push (ce_s, heap, *results, &cexpr);
+ VEC_safe_push (ce_s, stack, *results, &cexpr);
}
return;
}
- VEC_safe_push (ce_s, heap, *results, &cexpr);
+ VEC_safe_push (ce_s, stack, *results, &cexpr);
}
/* Process constraint T, performing various simplifications and then
@@ -2878,7 +2887,7 @@ bitpos_of_field (const tree fdecl)
static void
get_constraint_for_ptr_offset (tree ptr, tree offset,
- VEC (ce_s, heap) **results)
+ VEC (ce_s, stack) **results)
{
struct constraint_expr c;
unsigned int j, n;
@@ -2946,7 +2955,7 @@ get_constraint_for_ptr_offset (tree ptr,
c2.type = ADDRESSOF;
c2.offset = 0;
if (c2.var != c.var)
- VEC_safe_push (ce_s, heap, *results, &c2);
+ VEC_safe_push (ce_s, stack, *results, &c2);
temp = temp->next;
}
while (temp);
@@ -2981,7 +2990,7 @@ get_constraint_for_ptr_offset (tree ptr,
c2.var = temp->next->id;
c2.type = ADDRESSOF;
c2.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &c2);
+ VEC_safe_push (ce_s, stack, *results, &c2);
}
c.var = temp->id;
c.offset = 0;
@@ -3000,7 +3009,7 @@ get_constraint_for_ptr_offset (tree ptr,
as the lhs. */
static void
-get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
+get_constraint_for_component_ref (tree t, VEC(ce_s, stack) **results,
bool address_p, bool lhs_p)
{
tree orig_t = t;
@@ -3025,7 +3034,7 @@ get_constraint_for_component_ref (tree t
temp.offset = 0;
temp.var = integer_id;
temp.type = SCALAR;
- VEC_safe_push (ce_s, heap, *results, &temp);
+ VEC_safe_push (ce_s, stack, *results, &temp);
return;
}
@@ -3047,7 +3056,7 @@ get_constraint_for_component_ref (tree t
temp.offset = 0;
temp.var = anything_id;
temp.type = ADDRESSOF;
- VEC_safe_push (ce_s, heap, *results, &temp);
+ VEC_safe_push (ce_s, stack, *results, &temp);
return;
}
}
@@ -3088,7 +3097,7 @@ get_constraint_for_component_ref (tree t
bitpos, bitmaxsize))
{
cexpr.var = curr->id;
- VEC_safe_push (ce_s, heap, *results, &cexpr);
+ VEC_safe_push (ce_s, stack, *results, &cexpr);
if (address_p)
break;
}
@@ -3103,7 +3112,7 @@ get_constraint_for_component_ref (tree t
while (curr->next != NULL)
curr = curr->next;
cexpr.var = curr->id;
- VEC_safe_push (ce_s, heap, *results, &cexpr);
+ VEC_safe_push (ce_s, stack, *results, &cexpr);
}
else if (VEC_length (ce_s, *results) == 0)
/* Assert that we found *some* field there. The user couldn't be
@@ -3116,7 +3125,7 @@ get_constraint_for_component_ref (tree t
cexpr.type = SCALAR;
cexpr.var = anything_id;
cexpr.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &cexpr);
+ VEC_safe_push (ce_s, stack, *results, &cexpr);
}
}
else if (bitmaxsize == 0)
@@ -3162,7 +3171,7 @@ get_constraint_for_component_ref (tree t
This is needed so that we can handle dereferencing DEREF constraints. */
static void
-do_deref (VEC (ce_s, heap) **constraints)
+do_deref (VEC (ce_s, stack) **constraints)
{
struct constraint_expr *c;
unsigned int i = 0;
@@ -3189,7 +3198,7 @@ do_deref (VEC (ce_s, heap) **constraints
address of it. */
static void
-get_constraint_for_address_of (tree t, VEC (ce_s, heap) **results)
+get_constraint_for_address_of (tree t, VEC (ce_s, stack) **results)
{
struct constraint_expr *c;
unsigned int i;
@@ -3208,7 +3217,7 @@ get_constraint_for_address_of (tree t, V
/* Given a tree T, return the constraint expression for it. */
static void
-get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p,
+get_constraint_for_1 (tree t, VEC (ce_s, stack) **results, bool address_p,
bool lhs_p)
{
struct constraint_expr temp;
@@ -3240,7 +3249,7 @@ get_constraint_for_1 (tree t, VEC (ce_s,
temp.var = nonlocal_id;
temp.type = ADDRESSOF;
temp.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &temp);
+ VEC_safe_push (ce_s, stack, *results, &temp);
return;
}
@@ -3250,7 +3259,7 @@ get_constraint_for_1 (tree t, VEC (ce_s,
temp.var = readonly_id;
temp.type = SCALAR;
temp.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &temp);
+ VEC_safe_push (ce_s, stack, *results, &temp);
return;
}
@@ -3311,7 +3320,7 @@ get_constraint_for_1 (tree t, VEC (ce_s,
if (curr->offset - vi->offset < size)
{
cs.var = curr->id;
- VEC_safe_push (ce_s, heap, *results, &cs);
+ VEC_safe_push (ce_s, stack, *results, &cs);
}
else
break;
@@ -3346,17 +3355,17 @@ get_constraint_for_1 (tree t, VEC (ce_s,
{
unsigned int i;
tree val;
- VEC (ce_s, heap) *tmp = NULL;
+ VEC (ce_s, stack) *tmp = VEC_alloc (ce_s, stack, 32);
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, val)
{
struct constraint_expr *rhsp;
unsigned j;
get_constraint_for_1 (val, &tmp, address_p, lhs_p);
FOR_EACH_VEC_ELT (ce_s, tmp, j, rhsp)
- VEC_safe_push (ce_s, heap, *results, rhsp);
+ VEC_safe_push (ce_s, stack, *results, rhsp);
VEC_truncate (ce_s, tmp, 0);
}
- VEC_free (ce_s, heap, tmp);
+ VEC_free (ce_s, stack, tmp);
/* We do not know whether the constructor was complete,
so technically we have to add &NOTHING or &ANYTHING
like we do for an empty constructor as well. */
@@ -3377,7 +3386,7 @@ get_constraint_for_1 (tree t, VEC (ce_s,
temp.type = ADDRESSOF;
temp.var = nonlocal_id;
temp.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &temp);
+ VEC_safe_push (ce_s, stack, *results, &temp);
return;
}
default:;
@@ -3387,13 +3396,13 @@ get_constraint_for_1 (tree t, VEC (ce_s,
temp.type = ADDRESSOF;
temp.var = anything_id;
temp.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &temp);
+ VEC_safe_push (ce_s, stack, *results, &temp);
}
/* Given a gimple tree T, return the constraint expression vector for it. */
static void
-get_constraint_for (tree t, VEC (ce_s, heap) **results)
+get_constraint_for (tree t, VEC (ce_s, stack) **results)
{
gcc_assert (VEC_length (ce_s, *results) == 0);
@@ -3404,7 +3413,7 @@ get_constraint_for (tree t, VEC (ce_s, h
to be used as the rhs of a constraint. */
static void
-get_constraint_for_rhs (tree t, VEC (ce_s, heap) **results)
+get_constraint_for_rhs (tree t, VEC (ce_s, stack) **results)
{
gcc_assert (VEC_length (ce_s, *results) == 0);
@@ -3416,7 +3425,7 @@ get_constraint_for_rhs (tree t, VEC (ce_
entries in *LHSC. */
static void
-process_all_all_constraints (VEC (ce_s, heap) *lhsc, VEC (ce_s, heap) *rhsc)
+process_all_all_constraints (VEC (ce_s, stack) *lhsc, VEC (ce_s, stack) *rhsc)
{
struct constraint_expr *lhsp, *rhsp;
unsigned i, j;
@@ -3446,8 +3455,9 @@ static void
do_structure_copy (tree lhsop, tree rhsop)
{
struct constraint_expr *lhsp, *rhsp;
- VEC (ce_s, heap) *lhsc = NULL, *rhsc = NULL;
unsigned j;
+ VEC (ce_s, stack) *lhsc = VEC_alloc (ce_s, stack, 32);
+ VEC (ce_s, stack) *rhsc = VEC_alloc (ce_s, stack, 32);
get_constraint_for (lhsop, &lhsc);
get_constraint_for_rhs (rhsop, &rhsc);
@@ -3506,14 +3516,14 @@ do_structure_copy (tree lhsop, tree rhso
else
gcc_unreachable ();
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
}
/* Create constraints ID = { rhsc }. */
static void
-make_constraints_to (unsigned id, VEC(ce_s, heap) *rhsc)
+make_constraints_to (unsigned id, VEC(ce_s, stack) *rhsc)
{
struct constraint_expr *c;
struct constraint_expr includes;
@@ -3532,10 +3542,10 @@ make_constraints_to (unsigned id, VEC(ce
static void
make_constraint_to (unsigned id, tree op)
{
- VEC(ce_s, heap) *rhsc = NULL;
+ VEC(ce_s, stack) *rhsc = VEC_alloc (ce_s, stack, 32);
get_constraint_for_rhs (op, &rhsc);
make_constraints_to (id, rhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, rhsc);
}
/* Create a constraint ID = &FROM. */
@@ -3726,7 +3736,7 @@ get_function_part_constraint (varinfo_t
RHS. */
static void
-handle_rhs_call (gimple stmt, VEC(ce_s, heap) **results)
+handle_rhs_call (gimple stmt, VEC(ce_s, stack) **results)
{
struct constraint_expr rhsc;
unsigned i;
@@ -3780,7 +3790,7 @@ handle_rhs_call (gimple stmt, VEC(ce_s,
rhsc.var = get_call_use_vi (stmt)->id;
rhsc.offset = 0;
rhsc.type = SCALAR;
- VEC_safe_push (ce_s, heap, *results, &rhsc);
+ VEC_safe_push (ce_s, stack, *results, &rhsc);
}
/* The static chain escapes as well. */
@@ -3792,22 +3802,23 @@ handle_rhs_call (gimple stmt, VEC(ce_s,
&& gimple_call_lhs (stmt) != NULL_TREE
&& TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
{
- VEC(ce_s, heap) *tmpc = NULL;
struct constraint_expr lhsc, *c;
+ VEC(ce_s, stack) *tmpc = VEC_alloc (ce_s, stack, 32);
+
get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
lhsc.var = escaped_id;
lhsc.offset = 0;
lhsc.type = SCALAR;
FOR_EACH_VEC_ELT (ce_s, tmpc, i, c)
process_constraint (new_constraint (lhsc, *c));
- VEC_free(ce_s, heap, tmpc);
+ VEC_free(ce_s, stack, tmpc);
}
/* Regular functions return nonlocal memory. */
rhsc.var = nonlocal_id;
rhsc.offset = 0;
rhsc.type = SCALAR;
- VEC_safe_push (ce_s, heap, *results, &rhsc);
+ VEC_safe_push (ce_s, stack, *results, &rhsc);
}
/* For non-IPA mode, generate constraints necessary for a call
@@ -3815,10 +3826,10 @@ handle_rhs_call (gimple stmt, VEC(ce_s,
the LHS point to global and escaped variables. */
static void
-handle_lhs_call (gimple stmt, tree lhs, int flags, VEC(ce_s, heap) *rhsc,
+handle_lhs_call (gimple stmt, tree lhs, int flags, VEC(ce_s, stack) *rhsc,
tree fndecl)
{
- VEC(ce_s, heap) *lhsc = NULL;
+ VEC(ce_s, stack) *lhsc = VEC_alloc (ce_s, stack, 32);
get_constraint_for (lhs, &lhsc);
/* If the store is to a global decl make sure to
@@ -3828,11 +3839,11 @@ handle_lhs_call (gimple stmt, tree lhs,
&& DECL_P (lhs)
&& is_global_var (lhs))
{
- struct constraint_expr tmpc;
+ ce_s tmpc;
tmpc.var = escaped_id;
tmpc.offset = 0;
tmpc.type = SCALAR;
- VEC_safe_push (ce_s, heap, lhsc, &tmpc);
+ VEC_safe_push (ce_s, stack, lhsc, &tmpc);
}
/* If the call returns an argument unmodified override the rhs
@@ -3842,17 +3853,17 @@ handle_lhs_call (gimple stmt, tree lhs,
&& (flags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (stmt))
{
tree arg;
- rhsc = NULL;
+ VEC(ce_s, stack) *rhsc2 = VEC_alloc (ce_s, stack, 32);
arg = gimple_call_arg (stmt, flags & ERF_RETURN_ARG_MASK);
- get_constraint_for (arg, &rhsc);
- process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, rhsc);
+ get_constraint_for (arg, &rhsc2);
+ process_all_all_constraints (lhsc, rhsc2);
+ VEC_free (ce_s, stack, rhsc2);
}
else if (flags & ERF_NOALIAS)
{
varinfo_t vi;
- struct constraint_expr tmpc;
- rhsc = NULL;
+ ce_s tmpc;
+ VEC(ce_s, stack) *rhsc2 = VEC_alloc (ce_s, stack, 32);
vi = make_heapvar ("HEAP");
/* We delay marking allocated storage global until we know if
it escapes. */
@@ -3867,21 +3878,21 @@ handle_lhs_call (gimple stmt, tree lhs,
tmpc.var = vi->id;
tmpc.offset = 0;
tmpc.type = ADDRESSOF;
- VEC_safe_push (ce_s, heap, rhsc, &tmpc);
- process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_safe_push (ce_s, stack, rhsc2, &tmpc);
+ process_all_all_constraints (lhsc, rhsc2);
+ VEC_free (ce_s, stack, rhsc2);
}
else
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
+ VEC_free (ce_s, stack, lhsc);
}
/* For non-IPA mode, generate constraints necessary for a call of a
const function that returns a pointer in the statement STMT. */
static void
-handle_const_call (gimple stmt, VEC(ce_s, heap) **results)
+handle_const_call (gimple stmt, VEC(ce_s, stack) **results)
{
struct constraint_expr rhsc;
unsigned int k;
@@ -3896,34 +3907,35 @@ handle_const_call (gimple stmt, VEC(ce_s
rhsc.var = uses->id;
rhsc.offset = 0;
rhsc.type = SCALAR;
- VEC_safe_push (ce_s, heap, *results, &rhsc);
+ VEC_safe_push (ce_s, stack, *results, &rhsc);
}
/* May return arguments. */
for (k = 0; k < gimple_call_num_args (stmt); ++k)
{
tree arg = gimple_call_arg (stmt, k);
- VEC(ce_s, heap) *argc = NULL;
unsigned i;
struct constraint_expr *argp;
+ VEC(ce_s, stack) *argc = VEC_alloc (ce_s, stack, 32);
+
get_constraint_for_rhs (arg, &argc);
FOR_EACH_VEC_ELT (ce_s, argc, i, argp)
- VEC_safe_push (ce_s, heap, *results, argp);
- VEC_free(ce_s, heap, argc);
+ VEC_safe_push (ce_s, stack, *results, argp);
+ VEC_free(ce_s, stack, argc);
}
/* May return addresses of globals. */
rhsc.var = nonlocal_id;
rhsc.offset = 0;
rhsc.type = ADDRESSOF;
- VEC_safe_push (ce_s, heap, *results, &rhsc);
+ VEC_safe_push (ce_s, stack, *results, &rhsc);
}
/* For non-IPA mode, generate constraints necessary for a call to a
pure function in statement STMT. */
static void
-handle_pure_call (gimple stmt, VEC(ce_s, heap) **results)
+handle_pure_call (gimple stmt, VEC(ce_s, stack) **results)
{
struct constraint_expr rhsc;
unsigned i;
@@ -3958,12 +3970,12 @@ handle_pure_call (gimple stmt, VEC(ce_s,
rhsc.var = uses->id;
rhsc.offset = 0;
rhsc.type = SCALAR;
- VEC_safe_push (ce_s, heap, *results, &rhsc);
+ VEC_safe_push (ce_s, stack, *results, &rhsc);
}
rhsc.var = nonlocal_id;
rhsc.offset = 0;
rhsc.type = SCALAR;
- VEC_safe_push (ce_s, heap, *results, &rhsc);
+ VEC_safe_push (ce_s, stack, *results, &rhsc);
}
@@ -4004,9 +4016,9 @@ static bool
find_func_aliases_for_builtin_call (gimple t)
{
tree fndecl = gimple_call_fndecl (t);
- VEC(ce_s, heap) *lhsc = NULL;
- VEC(ce_s, heap) *rhsc = NULL;
varinfo_t fi;
+ VEC(ce_s, stack) *lhsc = VEC_alloc (ce_s, stack, 32);
+ VEC(ce_s, stack) *rhsc = VEC_alloc (ce_s, stack, 32);
if (fndecl != NULL_TREE
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
@@ -4059,16 +4071,17 @@ find_func_aliases_for_builtin_call (gimp
else
get_constraint_for (dest, &rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_truncate (ce_s, lhsc, 0);
+ VEC_truncate (ce_s, rhsc, 0);
}
get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc);
do_deref (&lhsc);
do_deref (&rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
return true;
}
case BUILT_IN_MEMSET:
@@ -4085,8 +4098,8 @@ find_func_aliases_for_builtin_call (gimp
get_constraint_for (res, &lhsc);
get_constraint_for (dest, &rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_truncate (ce_s, lhsc, 0);
+ VEC_truncate (ce_s, rhsc, 0);
}
get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
do_deref (&lhsc);
@@ -4104,7 +4117,9 @@ find_func_aliases_for_builtin_call (gimp
ac.offset = 0;
FOR_EACH_VEC_ELT (ce_s, lhsc, i, lhsp)
process_constraint (new_constraint (*lhsp, ac));
- VEC_free (ce_s, heap, lhsc);
+
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
return true;
}
case BUILT_IN_ASSUME_ALIGNED:
@@ -4116,8 +4131,8 @@ find_func_aliases_for_builtin_call (gimp
get_constraint_for (res, &lhsc);
get_constraint_for (dest, &rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
}
return true;
}
@@ -4157,8 +4172,9 @@ find_func_aliases_for_builtin_call (gimp
do_deref (&lhsc);
do_deref (&rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
return true;
}
break;
@@ -4182,7 +4198,7 @@ find_func_aliases_for_builtin_call (gimp
get_constraint_for (frame, &rhsc);
FOR_EACH_VEC_ELT (ce_s, rhsc, i, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
- VEC_free (ce_s, heap, rhsc);
+ VEC_truncate (ce_s, rhsc, 0);
/* Make the frame point to the function for
the trampoline adjustment call. */
@@ -4190,9 +4206,9 @@ find_func_aliases_for_builtin_call (gimp
do_deref (&lhsc);
get_constraint_for (nfunc, &rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, rhsc);
- VEC_free (ce_s, heap, lhsc);
+ VEC_free (ce_s, stack, rhsc);
+ VEC_free (ce_s, stack, lhsc);
return true;
}
}
@@ -4210,8 +4226,8 @@ find_func_aliases_for_builtin_call (gimp
get_constraint_for (tramp, &rhsc);
do_deref (&rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, rhsc);
- VEC_free (ce_s, heap, lhsc);
+ VEC_free (ce_s, stack, rhsc);
+ VEC_free (ce_s, stack, lhsc);
}
return true;
}
@@ -4233,8 +4249,8 @@ find_func_aliases_for_builtin_call (gimp
do_deref (&lhsc);
get_constraint_for (src, &rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
return true;
}
CASE_BUILT_IN_TM_LOAD (1):
@@ -4255,8 +4271,8 @@ find_func_aliases_for_builtin_call (gimp
get_constraint_for (addr, &rhsc);
do_deref (&rhsc);
process_all_all_constraints (lhsc, rhsc);
- VEC_free (ce_s, heap, lhsc);
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
return true;
}
/* Variadic argument handling needs to be handled in IPA
@@ -4285,7 +4301,7 @@ find_func_aliases_for_builtin_call (gimp
}
FOR_EACH_VEC_ELT (ce_s, lhsc, i, lhsp)
process_constraint (new_constraint (*lhsp, rhs));
- VEC_free (ce_s, heap, lhsc);
+ VEC_free (ce_s, stack, lhsc);
/* va_list is clobbered. */
make_constraint_to (get_call_clobber_vi (t)->id, valist);
return true;
@@ -4328,9 +4344,9 @@ static void
find_func_aliases_for_call (gimple t)
{
tree fndecl = gimple_call_fndecl (t);
- VEC(ce_s, heap) *lhsc = NULL;
- VEC(ce_s, heap) *rhsc = NULL;
varinfo_t fi;
+ VEC(ce_s, stack) *lhsc = VEC_alloc (ce_s, stack, 32);
+ VEC(ce_s, stack) *rhsc = VEC_alloc (ce_s, stack, 32);
if (fndecl != NULL_TREE
&& DECL_BUILT_IN (fndecl)
@@ -4341,7 +4357,6 @@ find_func_aliases_for_call (gimple t)
if (!in_ipa_mode
|| (fndecl && !fi->is_fn_info))
{
- VEC(ce_s, heap) *rhsc = NULL;
int flags = gimple_call_flags (t);
/* Const functions can return their arguments and addresses
@@ -4360,7 +4375,6 @@ find_func_aliases_for_call (gimple t)
handle_rhs_call (t, &rhsc);
if (gimple_call_lhs (t))
handle_lhs_call (t, gimple_call_lhs (t), flags, rhsc, fndecl);
- VEC_free (ce_s, heap, rhsc);
}
else
{
@@ -4398,11 +4412,11 @@ find_func_aliases_for_call (gimple t)
&& DECL_RESULT (fndecl)
&& DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
{
- VEC(ce_s, heap) *tem = NULL;
- VEC_safe_push (ce_s, heap, tem, &rhs);
+ VEC(ce_s, stack) *tem = VEC_alloc (ce_s, stack, 32);
+ VEC_safe_push (ce_s, stack, tem, &rhs);
do_deref (&tem);
rhs = VEC_index (ce_s, tem, 0);
- VEC_free(ce_s, heap, tem);
+ VEC_free(ce_s, stack, tem);
}
FOR_EACH_VEC_ELT (ce_s, lhsc, j, lhsp)
process_constraint (new_constraint (*lhsp, rhs));
@@ -4421,7 +4435,7 @@ find_func_aliases_for_call (gimple t)
lhs = get_function_part_constraint (fi, fi_result);
FOR_EACH_VEC_ELT (ce_s, rhsc, j, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, rhsc);
}
/* If we use a static chain, pass it along. */
@@ -4436,6 +4450,8 @@ find_func_aliases_for_call (gimple t)
process_constraint (new_constraint (lhs, *rhsp));
}
}
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
}
/* Walk statement T setting up aliasing constraints according to the
@@ -4447,10 +4463,10 @@ static void
find_func_aliases (gimple origt)
{
gimple t = origt;
- VEC(ce_s, heap) *lhsc = NULL;
- VEC(ce_s, heap) *rhsc = NULL;
struct constraint_expr *c;
varinfo_t fi;
+ VEC(ce_s, stack) *lhsc = VEC_alloc (ce_s, stack, 32);
+ VEC(ce_s, stack) *rhsc = VEC_alloc (ce_s, stack, 32);
/* Now build constraints expressions. */
if (gimple_code (t) == GIMPLE_PHI)
@@ -4534,18 +4550,19 @@ find_func_aliases (gimple origt)
else
{
/* All other operations are merges. */
- VEC (ce_s, heap) *tmp = NULL;
struct constraint_expr *rhsp;
unsigned i, j;
+ VEC (ce_s, stack) *tmp = VEC_alloc (ce_s, stack, 32);
+
get_constraint_for_rhs (gimple_assign_rhs1 (t), &rhsc);
for (i = 2; i < gimple_num_ops (t); ++i)
{
get_constraint_for_rhs (gimple_op (t, i), &tmp);
FOR_EACH_VEC_ELT (ce_s, tmp, j, rhsp)
- VEC_safe_push (ce_s, heap, rhsc, rhsp);
+ VEC_safe_push (ce_s, stack, rhsc, rhsp);
VEC_truncate (ce_s, tmp, 0);
}
- VEC_free (ce_s, heap, tmp);
+ VEC_free (ce_s, stack, tmp);
}
process_all_all_constraints (lhsc, rhsc);
}
@@ -4607,16 +4624,16 @@ find_func_aliases (gimple origt)
any global memory. */
if (op)
{
- VEC(ce_s, heap) *lhsc = NULL;
struct constraint_expr rhsc, *lhsp;
unsigned j;
+
get_constraint_for (op, &lhsc);
rhsc.var = nonlocal_id;
rhsc.offset = 0;
rhsc.type = SCALAR;
FOR_EACH_VEC_ELT (ce_s, lhsc, j, lhsp)
process_constraint (new_constraint (*lhsp, rhsc));
- VEC_free (ce_s, heap, lhsc);
+ VEC_truncate (ce_s, lhsc, 0);
}
}
for (i = 0; i < gimple_asm_ninputs (t); ++i)
@@ -4640,8 +4657,8 @@ find_func_aliases (gimple origt)
}
}
- VEC_free (ce_s, heap, rhsc);
- VEC_free (ce_s, heap, lhsc);
+ VEC_free (ce_s, stack, rhsc);
+ VEC_free (ce_s, stack, lhsc);
}
@@ -4651,14 +4668,15 @@ find_func_aliases (gimple origt)
static void
process_ipa_clobber (varinfo_t fi, tree ptr)
{
- VEC(ce_s, heap) *ptrc = NULL;
struct constraint_expr *c, lhs;
unsigned i;
+ VEC(ce_s, stack) *ptrc = VEC_alloc (ce_s, stack, 32);
+
get_constraint_for_rhs (ptr, &ptrc);
lhs = get_function_part_constraint (fi, fi_clobbers);
FOR_EACH_VEC_ELT (ce_s, ptrc, i, c)
process_constraint (new_constraint (lhs, *c));
- VEC_free (ce_s, heap, ptrc);
+ VEC_free (ce_s, stack, ptrc);
}
/* Walk statement T setting up clobber and use constraints according to the
@@ -4669,9 +4687,9 @@ static void
find_func_clobbers (gimple origt)
{
gimple t = origt;
- VEC(ce_s, heap) *lhsc = NULL;
- VEC(ce_s, heap) *rhsc = NULL;
varinfo_t fi;
+ VEC(ce_s, stack) *lhsc = VEC_alloc (ce_s, stack, 32);
+ VEC(ce_s, stack) *rhsc = VEC_alloc (ce_s, stack, 32);
/* Add constraints for clobbered/used in IPA mode.
We are not interested in what automatic variables are clobbered
@@ -4703,13 +4721,15 @@ find_func_clobbers (gimple origt)
&& auto_var_in_fn_p
(TREE_OPERAND (TREE_OPERAND (tem, 0), 0), cfun->decl))))
{
- struct constraint_expr lhsc, *rhsp;
+ struct constraint_expr lhsc_expr, *rhsp;
unsigned i;
- lhsc = get_function_part_constraint (fi, fi_clobbers);
- get_constraint_for_address_of (lhs, &rhsc);
- FOR_EACH_VEC_ELT (ce_s, rhsc, i, rhsp)
- process_constraint (new_constraint (lhsc, *rhsp));
- VEC_free (ce_s, heap, rhsc);
+ VEC(ce_s, stack) *rhsc2 = VEC_alloc (ce_s, stack, 32);
+
+ lhsc_expr = get_function_part_constraint (fi, fi_clobbers);
+ get_constraint_for_address_of (lhs, &rhsc2);
+ FOR_EACH_VEC_ELT (ce_s, rhsc2, i, rhsp)
+ process_constraint (new_constraint (lhsc_expr, *rhsp));
+ VEC_free (ce_s, stack, rhsc2);
}
}
@@ -4733,15 +4753,16 @@ find_func_clobbers (gimple origt)
{
struct constraint_expr lhs, *rhsp;
unsigned i;
+ VEC(ce_s, stack) *rhsc2 = VEC_alloc (ce_s, stack, 32);
+
lhs = get_function_part_constraint (fi, fi_uses);
- get_constraint_for_address_of (rhs, &rhsc);
- FOR_EACH_VEC_ELT (ce_s, rhsc, i, rhsp)
+ get_constraint_for_address_of (rhs, &rhsc2);
+ FOR_EACH_VEC_ELT (ce_s, rhsc2, i, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, rhsc2);
}
}
-
- if (is_gimple_call (t))
+ else if (is_gimple_call (t))
{
varinfo_t cfi = NULL;
tree decl = gimple_call_fndecl (t);
@@ -4786,12 +4807,13 @@ find_func_clobbers (gimple origt)
lhs = get_function_part_constraint (fi, fi_clobbers);
FOR_EACH_VEC_ELT (ce_s, lhsc, i, lhsp)
process_constraint (new_constraint (lhs, *lhsp));
- VEC_free (ce_s, heap, lhsc);
get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc);
lhs = get_function_part_constraint (fi, fi_uses);
FOR_EACH_VEC_ELT (ce_s, rhsc, i, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
- VEC_free (ce_s, heap, rhsc);
+
+ VEC_free (ce_s, stack, lhsc);
+ VEC_free (ce_s, stack, rhsc);
return;
}
/* The following function clobbers memory pointed to by
@@ -4806,7 +4828,7 @@ find_func_clobbers (gimple origt)
lhs = get_function_part_constraint (fi, fi_clobbers);
FOR_EACH_VEC_ELT (ce_s, lhsc, i, lhsp)
process_constraint (new_constraint (lhs, *lhsp));
- VEC_free (ce_s, heap, lhsc);
+ VEC_free (ce_s, stack, lhsc);
return;
}
/* The following functions clobber their second and third
@@ -4876,7 +4898,6 @@ find_func_clobbers (gimple origt)
get_constraint_for_address_of (arg, &rhsc);
FOR_EACH_VEC_ELT (ce_s, rhsc, j, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
- VEC_free (ce_s, heap, rhsc);
}
/* Build constraints for propagating clobbers/uses along the
@@ -4889,6 +4910,7 @@ find_func_clobbers (gimple origt)
anything_id);
make_constraint_from (first_vi_for_offset (fi, fi_uses),
anything_id);
+ VEC_free (ce_s, stack, rhsc);
return;
}
@@ -4911,6 +4933,7 @@ find_func_clobbers (gimple origt)
if ((vi = lookup_call_use_vi (t)) != NULL)
make_copy_constraint (first_vi_for_offset (fi, fi_uses),
vi->id);
+ VEC_free (ce_s, stack, rhsc);
return;
}
@@ -4937,7 +4960,7 @@ find_func_clobbers (gimple origt)
anything_id);
}
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, rhsc);
}
@@ -5597,7 +5620,7 @@ create_variable_info_for (tree decl, con
if (DECL_INITIAL (decl)
&& vnode->analyzed)
{
- VEC (ce_s, heap) *rhsc = NULL;
+ VEC (ce_s, stack) *rhsc = VEC_alloc (ce_s, stack, 32);
struct constraint_expr lhs, *rhsp;
unsigned i;
get_constraint_for_rhs (DECL_INITIAL (decl), &rhsc);
@@ -5616,7 +5639,7 @@ create_variable_info_for (tree decl, con
FOR_EACH_VEC_ELT (ce_s, rhsc, i, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
}
- VEC_free (ce_s, heap, rhsc);
+ VEC_free (ce_s, stack, rhsc);
}
}
}
=== modified file 'gcc/vecir.h'
--- gcc/vecir.h 2010-05-15 19:02:11 +0000
+++ gcc/vecir.h 2012-08-18 16:43:02 +0000
@@ -28,6 +28,9 @@ along with GCC; see the file COPYING3.
DEF_VEC_P(tree);
DEF_VEC_ALLOC_P(tree,gc);
DEF_VEC_ALLOC_P(tree,heap);
+DEF_VEC_ALLOC_P_STACK(tree);
+#define VEC_tree_stack_alloc(alloc) \
+ VEC_stack_alloc (tree, alloc)
/* A varray of gimple statements. */
DEF_VEC_P(gimple);
=== modified file 'gcc/tree-ssa-sccvn.c'
--- gcc/tree-ssa-sccvn.c 2012-08-16 14:27:51 +0000
+++ gcc/tree-ssa-sccvn.c 2012-08-18 16:43:02 +0000
@@ -3644,8 +3650,8 @@ DEF_VEC_ALLOC_O(ssa_op_iter,heap);
static bool
extract_and_process_scc_for_name (tree name)
{
- VEC (tree, heap) *scc = NULL;
tree x;
+ VEC (tree, stack) *scc = VEC_alloc (tree, stack, 16);
/* Found an SCC, pop the components off the SCC stack and
process them. */
@@ -3654,7 +3660,7 @@ extract_and_process_scc_for_name (tree n
x = VEC_pop (tree, sccstack);
VN_INFO (x)->on_sccstack = false;
- VEC_safe_push (tree, heap, scc, x);
+ VEC_safe_push (tree, stack, scc, x);
} while (x != name);
/* Bail out of SCCVN in case a SCC turns out to be incredibly large. */
@@ -3678,7 +3684,7 @@ extract_and_process_scc_for_name (tree n
process_scc (scc);
- VEC_free (tree, heap, scc);
+ VEC_free (tree, stack, scc);
return true;
}
@@ -2474,7 +2479,7 @@ vn_phi_insert (gimple phi, tree result)
/* Print set of components in strongly connected component SCC to OUT. */
static void
-print_scc (FILE *out, VEC (tree, heap) *scc)
+print_scc (FILE *out, VEC (tree, stack) *scc)
{
tree var;
unsigned int i;
@@ -3513,7 +3518,7 @@ compare_ops (const void *pa, const void
array will give you the members in RPO order. */
static void
-sort_scc (VEC (tree, heap) *scc)
+sort_scc (VEC (tree, stack) *scc)
{
VEC_qsort (tree, scc, compare_ops);
}
@@ -3564,7 +3569,7 @@ copy_reference (vn_reference_t oref, vn_
/* Process a strongly connected component in the SSA graph. */
static void
-process_scc (VEC (tree, heap) *scc)
+process_scc (VEC (tree, stack) *scc)
{
tree var;
unsigned int i;
^ permalink raw reply [flat|nested] 24+ messages in thread
* enlarge hot allocation pools
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
` (5 preceding siblings ...)
2012-08-19 18:30 ` obstack for equiv_class_label, more vectors on stack Dimitrios Apostolou
@ 2012-08-19 18:31 ` Dimitrios Apostolou
2012-08-19 21:55 ` Steven Bosscher
2012-08-20 14:55 ` [DF] RFC: obstacks in DF Dimitrios Apostolou
2012-08-20 17:04 ` failed attempt: retain identifier length from frontend to backend Dimitrios Apostolou
8 siblings, 1 reply; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-19 18:31 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev
[-- Attachment #1: Type: TEXT/PLAIN, Size: 618 bytes --]
Hello,
2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
* gcc/cselib.c (cselib_init): Make allocation pools larger since
they are too hot and show to expand often on the profiler.
* gcc/df-problems.c (df_chain_alloc): Same.
* gcc/et-forest.c (et_new_occ, et_new_tree): Same.
* gcc/tree-ssa-pre.c (init_pre): Same
These allocation pools are the ones that I've noticed calling malloc() too
often, for expanding their size. Also I don't like the way the pools are
created in et_new_{occ,tree}() but couldn't find a single point to move
the initialisation either. Any ideas on this one?
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/PLAIN, Size: 3210 bytes --]
2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
* gcc/cselib.c (cselib_init): Make allocation pools larger since
they are too hot and show to expand often on the profiler.
* gcc/df-problems.c (df_chain_alloc): Same.
* gcc/et-forest.c (et_new_occ, et_new_tree): Same.
* gcc/tree-ssa-pre.c (init_pre): Same
=== modified file 'gcc/cselib.c'
--- gcc/cselib.c 2012-08-02 22:39:57 +0000
+++ gcc/cselib.c 2012-08-19 15:13:28 +0000
@@ -2659,12 +2659,12 @@ void
cselib_init (int record_what)
{
elt_list_pool = create_alloc_pool ("elt_list",
- sizeof (struct elt_list), 10);
+ sizeof (struct elt_list), 128);
elt_loc_list_pool = create_alloc_pool ("elt_loc_list",
- sizeof (struct elt_loc_list), 10);
+ sizeof (struct elt_loc_list), 128);
cselib_val_pool = create_alloc_pool ("cselib_val_list",
- sizeof (cselib_val), 10);
- value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100);
+ sizeof (cselib_val), 128);
+ value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 128);
cselib_record_memory = record_what & CSELIB_RECORD_MEMORY;
cselib_preserve_constants = record_what & CSELIB_PRESERVE_CONSTANTS;
cselib_any_perm_equivs = false;
=== modified file 'gcc/df-problems.c'
--- gcc/df-problems.c 2012-08-17 09:42:06 +0000
+++ gcc/df-problems.c 2012-08-19 15:29:37 +0000
@@ -1993,7 +1993,7 @@ df_chain_alloc (bitmap all_blocks ATTRIB
{
df_chain_remove_problem ();
df_chain->block_pool = create_alloc_pool ("df_chain_block pool",
- sizeof (struct df_link), 50);
+ sizeof (struct df_link), 128);
df_chain->optional_p = true;
}
=== modified file 'gcc/et-forest.c'
--- gcc/et-forest.c 2012-05-31 16:43:31 +0000
+++ gcc/et-forest.c 2012-08-19 15:50:25 +0000
@@ -444,8 +444,8 @@ et_new_occ (struct et_node *node)
{
struct et_occ *nw;
- if (!et_occurrences)
- et_occurrences = create_alloc_pool ("et_occ pool", sizeof (struct et_occ), 300);
+ if (!et_occurrences)
+ et_occurrences = create_alloc_pool ("et_occ pool", sizeof (struct et_occ), 1024);
nw = (struct et_occ *) pool_alloc (et_occurrences);
nw->of = node;
@@ -467,8 +467,8 @@ et_new_tree (void *data)
{
struct et_node *nw;
- if (!et_nodes)
- et_nodes = create_alloc_pool ("et_node pool", sizeof (struct et_node), 300);
+ if (!et_nodes)
+ et_nodes = create_alloc_pool ("et_node pool", sizeof (struct et_node), 512);
nw = (struct et_node *) pool_alloc (et_nodes);
nw->data = data;
=== modified file 'gcc/tree-ssa-pre.c'
--- gcc/tree-ssa-pre.c 2012-08-18 06:31:26 +0000
+++ gcc/tree-ssa-pre.c 2012-08-19 15:28:21 +0000
@@ -4812,9 +4812,9 @@ init_pre (bool do_fre)
phi_translate_table.create (5110);
expression_to_id.create (num_ssa_names * 3);
bitmap_set_pool = create_alloc_pool ("Bitmap sets",
- sizeof (struct bitmap_set), 30);
+ sizeof (struct bitmap_set), 128);
pre_expr_pool = create_alloc_pool ("pre_expr nodes",
- sizeof (struct pre_expr_d), 30);
+ sizeof (struct pre_expr_d), 32);
FOR_ALL_BB (bb)
{
EXP_GEN (bb) = bitmap_set_new ();
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: enlarge hot allocation pools
2012-08-19 18:31 ` enlarge hot allocation pools Dimitrios Apostolou
@ 2012-08-19 21:55 ` Steven Bosscher
2012-08-20 3:26 ` Dimitrios Apostolou
0 siblings, 1 reply; 24+ messages in thread
From: Steven Bosscher @ 2012-08-19 21:55 UTC (permalink / raw)
To: Dimitrios Apostolou; +Cc: gcc-patches, Andrey Belevantsev
On Sun, Aug 19, 2012 at 8:31 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
> Hello,
>
> 2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
>
> * gcc/cselib.c (cselib_init): Make allocation pools larger since
> they are too hot and show to expand often on the profiler.
> * gcc/df-problems.c (df_chain_alloc): Same.
> * gcc/et-forest.c (et_new_occ, et_new_tree): Same.
> * gcc/tree-ssa-pre.c (init_pre): Same
>
>
> These allocation pools are the ones that I've noticed calling malloc() too
> often, for expanding their size.
I don't like the way these pools are sized with a seemingly arbitrary
initial size. They're there to hold something, and they grow because
there are "more somethings" than initially guessed. I think you should
look at what the pools hold and choose an initial size based on some
representative measure. E.g. if a pool holds some kind of expressions,
then you should be able to make an initial guess of the size of the
pool based on the number of pseudos or ssa names. Ideally you'd simply
"derive" the initial pool size by a regression analysis of the final
pool size and some potential representative measures (# of regs, basic
blocks, edges, whatever).
> Also I don't like the way the pools are
> created in et_new_{occ,tree}() but couldn't find a single point to move the
> initialisation either. Any ideas on this one?
Just create a new function to initialize (destroy) the pools and call
it from calculate_dominance_info (free_dominance_info).
Ciao!
Steven
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: enlarge hot allocation pools
2012-08-19 21:55 ` Steven Bosscher
@ 2012-08-20 3:26 ` Dimitrios Apostolou
0 siblings, 0 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-20 3:26 UTC (permalink / raw)
To: Steven Bosscher; +Cc: gcc-patches, Andrey Belevantsev
Hi Steven,
On Sun, 19 Aug 2012, Steven Bosscher wrote:
> On Sun, Aug 19, 2012 at 8:31 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
>> Hello,
>>
>> 2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
>>
>> * gcc/cselib.c (cselib_init): Make allocation pools larger since
>> they are too hot and show to expand often on the profiler.
>> * gcc/df-problems.c (df_chain_alloc): Same.
>> * gcc/et-forest.c (et_new_occ, et_new_tree): Same.
>> * gcc/tree-ssa-pre.c (init_pre): Same
>>
>>
>> These allocation pools are the ones that I've noticed calling malloc() too
>> often, for expanding their size.
>
> I don't like the way these pools are sized with a seemingly arbitrary
> initial size. They're there to hold something, and they grow because
> there are "more somethings" than initially guessed. I think you should
> look at what the pools hold and choose an initial size based on some
> representative measure. E.g. if a pool holds some kind of expressions,
> then you should be able to make an initial guess of the size of the
> pool based on the number of pseudos or ssa names. Ideally you'd simply
> "derive" the initial pool size by a regression analysis of the final
> pool size and some potential representative measures (# of regs, basic
> blocks, edges, whatever).
Some time ago I tried changing the pool allocator growth strategy from
linear to exponential, doubling the size of the pool chunk every time it
needed another chunk. It was for the exact same reason, to set the pool
size according to their contents. Unfortunately I remember it didn't make
a difference so I dumped it and only manually changed the important pools,
which made a small difference. I'll now try deducing information on the
size at runtime, thanks for the tip.
Dimitris
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: alloc_pool for tree-ssa-pre.c:phi_translate_table
2012-08-19 18:30 ` alloc_pool for tree-ssa-pre.c:phi_translate_table Dimitrios Apostolou
@ 2012-08-20 7:38 ` Richard Guenther
2012-08-20 9:29 ` Jakub Jelinek
0 siblings, 1 reply; 24+ messages in thread
From: Richard Guenther @ 2012-08-20 7:38 UTC (permalink / raw)
To: Dimitrios Apostolou; +Cc: gcc-patches, Andrey Belevantsev
On Sun, Aug 19, 2012 at 8:30 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
>
>
> 2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
>
> * gcc/tree-ssa-pre.c (phi_translate_pool): New static global
> alloc_pool, used for allocating struct expr_pred_trans_d for
> phi_translate_table.
> (phi_trans_add, init_pre, fini_pre): Use it, avoids thousand of
> malloc() and free() calls.
>
>
> This avoids lots of malloc/free calls and slow iterations during numerous
> htab_delete() in fini_pre(). Tested on pre C++-snapshot, will update info as
> soon as a post C++ one is available.
Ok, if bootstrap / testing still succeeds.
Thanks,
Richard.
>
> Thanks,
> Dimitris
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Speedups/Cleanups: End of GSOC patch collection
2012-08-18 16:37 ` Dimitrios Apostolou
@ 2012-08-20 9:20 ` Dodji Seketeli
2012-08-24 15:41 ` Tom Tromey
0 siblings, 1 reply; 24+ messages in thread
From: Dodji Seketeli @ 2012-08-20 9:20 UTC (permalink / raw)
To: Dimitrios Apostolou
Cc: gcc-patches, Andrey Belevantsev, Ian Lance Taylor, Tom Tromey
Dimitrios Apostolou <jimis@gmx.net> a écrit:
[...]
> * include/libiberty.h (XOBDELETE, XOBGROW, XOBGROWVEC, XOBSHRINK)
> (XOBSHRINKVEC, XOBFINISH): New type-safe macros for obstack
> operations.
> (XOBFINISH): Changed to return (T *) instead of T. All callers
> updated.
> * libcpp/include/symtab.h (obstack_chunk_alloc)
> (obstack_chunk_free): Define, so that obstack_init() can be used.
> * libcpp/internal.h (struct cset_converter): Same.
> * libcpp/files.c (_cpp_init_files): Changed _obstack_begin() to
> obstack_init().
> * libcpp/identifiers.c (_cpp_init_hashtable): Same.
> * libcpp/symtab.c (ht_create): Same.
> * libcpp/init.c (cpp_create_reader): Same.
>
[...]
> +++ libcpp/include/symtab.h 2012-08-18 15:07:01 +0000
[...]
> +#ifndef obstack_chunk_alloc
Please add a comment here, as you did bellow in hunk for
libcpp/internal.h:
> +#ifndef obstack_chunk_alloc
> + /* Needed for calling obstack_init(). */
> + #define obstack_chunk_alloc (void *(*) (long)) xmalloc
> + #define obstack_chunk_free (void (*) (void *)) free
> +#endif
> + #define obstack_chunk_alloc (void *(*) (long)) xmalloc
> + #define obstack_chunk_free (void (*) (void *)) free
> +#endif
[...]
With these changes, the libcpp parts look OK to me if they still
boostrap post c++ conversion. I am not a maintainer so I a deferring to
Tom and the other maintainers.
Thanks.
--
Dodji
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: alloc_pool for tree-ssa-pre.c:phi_translate_table
2012-08-20 7:38 ` Richard Guenther
@ 2012-08-20 9:29 ` Jakub Jelinek
2012-08-20 9:37 ` Dimitrios Apostolou
0 siblings, 1 reply; 24+ messages in thread
From: Jakub Jelinek @ 2012-08-20 9:29 UTC (permalink / raw)
To: Richard Guenther; +Cc: Dimitrios Apostolou, gcc-patches
On Mon, Aug 20, 2012 at 09:37:39AM +0200, Richard Guenther wrote:
> On Sun, Aug 19, 2012 at 8:30 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
> >
> >
> > 2012-08-19 Dimitrios Apostolou <jimis@gmx.net>
> >
> > * gcc/tree-ssa-pre.c (phi_translate_pool): New static global
> > alloc_pool, used for allocating struct expr_pred_trans_d for
> > phi_translate_table.
> > (phi_trans_add, init_pre, fini_pre): Use it, avoids thousand of
> > malloc() and free() calls.
> >
> >
> > This avoids lots of malloc/free calls and slow iterations during numerous
> > htab_delete() in fini_pre(). Tested on pre C++-snapshot, will update info as
> > soon as a post C++ one is available.
>
> Ok, if bootstrap / testing still succeeds.
I'd note for all the recently posted patches from Dimitrios, the gcc/
prefix doesn't belong to the ChangeLog entry pathnames, the filenames are
relative to the corresponding ChangeLog location.
Jakub
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: alloc_pool for tree-ssa-pre.c:phi_translate_table
2012-08-20 9:29 ` Jakub Jelinek
@ 2012-08-20 9:37 ` Dimitrios Apostolou
0 siblings, 0 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-20 9:37 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Richard Guenther, gcc-patches
On Mon, 20 Aug 2012, Jakub Jelinek wrote:
>
> I'd note for all the recently posted patches from Dimitrios, the gcc/
> prefix doesn't belong to the ChangeLog entry pathnames, the filenames are
> relative to the corresponding ChangeLog location.
>
Ah sorry, it's what the mklog utility generates, it seems I got carried
away over-using it. :-)
Dimitris
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [graphds.h] Allocate graph from obstack
2012-08-19 16:55 ` Richard Guenther
@ 2012-08-20 12:04 ` Paolo Bonzini
2012-08-20 12:17 ` Richard Guenther
2012-08-20 13:17 ` Dimitrios Apostolou
0 siblings, 2 replies; 24+ messages in thread
From: Paolo Bonzini @ 2012-08-20 12:04 UTC (permalink / raw)
To: Richard Guenther; +Cc: Dimitrios Apostolou, gcc-patches, Andrey Belevantsev
Il 19/08/2012 18:55, Richard Guenther ha scritto:
>> > Initially I had one obstack per struct graph, which was better than using
>> > XNEW for every edge, but still obstack_init() called from new_graph() was
>> > too frequent.
>> >
>> > So in this iteration of the patch the obstack is static global, initialised
>> > once and never freed. Please advise on whether this is acceptable, and also
>> > where I should initialise the obstack once, and avoid checking if it's NULL
>> > in every use.
>> >
>> > Minor speed gains (couple of ms), tested with pre-C++ conversion snapshot,
>> > I'll retest soon and post update.
> Either an obstack per graph or the ability to specify an obstack for allocation.
> A global obstack with global lifetime is bad IMHO.
Dimitrios's patch has a per-file obstack with per-pass lifetime, which I
think is the right solution---but putting graph_obstack as a static
variable in graphds.h is uuuugly. You can just move the declaration to
each file separately, and give it a better name perhaps (e.g.
loop_graph_obstack).
Paolo
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [graphds.h] Allocate graph from obstack
2012-08-20 12:04 ` Paolo Bonzini
@ 2012-08-20 12:17 ` Richard Guenther
2012-08-20 13:17 ` Dimitrios Apostolou
1 sibling, 0 replies; 24+ messages in thread
From: Richard Guenther @ 2012-08-20 12:17 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Dimitrios Apostolou, gcc-patches, Andrey Belevantsev
On Mon, Aug 20, 2012 at 2:03 PM, Paolo Bonzini <bonzini@gnu.org> wrote:
> Il 19/08/2012 18:55, Richard Guenther ha scritto:
>>> > Initially I had one obstack per struct graph, which was better than using
>>> > XNEW for every edge, but still obstack_init() called from new_graph() was
>>> > too frequent.
>>> >
>>> > So in this iteration of the patch the obstack is static global, initialised
>>> > once and never freed. Please advise on whether this is acceptable, and also
>>> > where I should initialise the obstack once, and avoid checking if it's NULL
>>> > in every use.
>>> >
>>> > Minor speed gains (couple of ms), tested with pre-C++ conversion snapshot,
>>> > I'll retest soon and post update.
>> Either an obstack per graph or the ability to specify an obstack for allocation.
>> A global obstack with global lifetime is bad IMHO.
>
> Dimitrios's patch has a per-file obstack with per-pass lifetime, which I
> think is the right solution---but putting graph_obstack as a static
> variable in graphds.h is uuuugly. You can just move the declaration to
> each file separately, and give it a better name perhaps (e.g.
> loop_graph_obstack).
Well, I see that the way it is constructed is that you can at most have a
single live graph at the same time (using the same obstack). That's a
big limitation IMHO. Now, if the users would manage the obstack completely
and instead would obstack_init()/free() them that would be different. Of course
the outcome is exactly as with the initial patch having the obstack per
struct graph.
The present patch has too much low-level stuff exposed and does not easily
allow putting other data on the same obstack.
So I'd vote for managing the obstack completely in the caller for flexibility.
Some may want to allocate auxiliar data on the same obstack for example.
Richard.
> Paolo
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [graphds.h] Allocate graph from obstack
2012-08-20 12:04 ` Paolo Bonzini
2012-08-20 12:17 ` Richard Guenther
@ 2012-08-20 13:17 ` Dimitrios Apostolou
1 sibling, 0 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-20 13:17 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Richard Guenther, gcc-patches, Andrey Belevantsev
Hi Paolo,
On Mon, 20 Aug 2012, Paolo Bonzini wrote:
> Il 19/08/2012 18:55, Richard Guenther ha scritto:
>>>> Initially I had one obstack per struct graph, which was better than using
>>>> XNEW for every edge, but still obstack_init() called from new_graph() was
>>>> too frequent.
>>>>
>>>> So in this iteration of the patch the obstack is static global, initialised
>>>> once and never freed. Please advise on whether this is acceptable, and also
>>>> where I should initialise the obstack once, and avoid checking if it's NULL
>>>> in every use.
>>>>
>>>> Minor speed gains (couple of ms), tested with pre-C++ conversion snapshot,
>>>> I'll retest soon and post update.
>> Either an obstack per graph or the ability to specify an obstack for allocation.
>> A global obstack with global lifetime is bad IMHO.
>
> Dimitrios's patch has a per-file obstack with per-pass lifetime
Notice that I never call XOBDELETE with NULL argument, I only free the
first object, which means that the 4KB per obstack overhead is retained
until program exit, I did that to save on malloc calls.
Thanks,
Dimitris
^ permalink raw reply [flat|nested] 24+ messages in thread
* [DF] RFC: obstacks in DF
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
` (6 preceding siblings ...)
2012-08-19 18:31 ` enlarge hot allocation pools Dimitrios Apostolou
@ 2012-08-20 14:55 ` Dimitrios Apostolou
2012-08-20 15:32 ` Steven Bosscher
2012-08-20 17:04 ` failed attempt: retain identifier length from frontend to backend Dimitrios Apostolou
8 siblings, 1 reply; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-20 14:55 UTC (permalink / raw)
To: gcc-patches; +Cc: Paolo Bonzini, Andrey Belevantsev, Michael Matz
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1146 bytes --]
Hi,
while I was happy using obstacks in other parts of the compiler I thought
they would provide a handy solution for the XNEWVECs/XRESIZEVECs in
df-scan.c, especially df_install_refs() which is the heaviest malloc()
user after the rest of my patches.
In the process I realised that obstacks weren't exactly suitable (thanks
matz for helping on IRC), nevertheless I have a patch which is stable, a
bit faster and more memory friendly (don't know why, but RSS memory for
common non-pathological compilations, was smaller). However after trying
various incorrect changes I'm aware that there are leaks in there that
can't be closed without dirty hacks, so I gave up.
I'm posting the simplest but stable version of my changes and would really
like to hear ideas. There are "holes" in the obstack that should have been
free'd, but in the end I didn't see memory increase. I don't know what
would happen for huge functions that keep the obstack alive for long, I
didn't have such testcase. Finally, I think my next try will involve
converting the chains to pool_alloc'ed linked list, do you think that
makes sense?
Thanks,
Dimitris
[-- Attachment #2: Type: TEXT/plain, Size: 4285 bytes --]
=== modified file 'gcc/df-scan.c'
--- gcc/df-scan.c 2012-07-16 11:32:42 +0000
+++ gcc/df-scan.c 2012-08-20 14:01:59 +0000
@@ -184,6 +184,17 @@ struct df_scan_problem_data
bitmap_obstack insn_bitmaps;
};
+/* Obstack for storing all of all of
+ insn_info->{defs,uses,eq_uses,mw_hardregs} and
+ bb_info->artificial_{defs,uses}. */
+static struct obstack df_refs_obstack;
+
+/* Keep the obstack initialised (only 4k overhead) and use this pointer to
+ actually empty it fast. */
+static void *df_first_refs_obj;
+static int df_refs_obstack_is_init;
+
+
typedef struct df_scan_bb_info *df_scan_bb_info_t;
@@ -193,36 +204,13 @@ df_scan_free_internal (void)
{
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) df_scan->problem_data;
- unsigned int i;
- basic_block bb;
- /* The vectors that hold the refs are not pool allocated because
- they come in many sizes. This makes them impossible to delete
- all at once. */
- for (i = 0; i < DF_INSN_SIZE(); i++)
- {
- struct df_insn_info *insn_info = DF_INSN_UID_GET(i);
- /* Skip the insns that have no insn_info or have been
- deleted. */
- if (insn_info)
- {
- df_scan_free_ref_vec (insn_info->defs);
- df_scan_free_ref_vec (insn_info->uses);
- df_scan_free_ref_vec (insn_info->eq_uses);
- df_scan_free_mws_vec (insn_info->mw_hardregs);
- }
- }
-
- FOR_ALL_BB (bb)
- {
- unsigned int bb_index = bb->index;
- struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb_index);
- if (bb_info)
- {
- df_scan_free_ref_vec (bb_info->artificial_defs);
- df_scan_free_ref_vec (bb_info->artificial_uses);
- }
- }
+ /* Delete at once all vectors that hold the refs (all of
+ insn_info->{defs,uses,eq_uses,mw_hardregs} and
+ bb_info->artificial_{defs,uses}) but keep the obstack initialised, so
+ that it's ready for more BBs. */
+ obstack_free (&df_refs_obstack, df_first_refs_obj);
+ df_first_refs_obj = NULL;
free (df->def_info.refs);
free (df->def_info.begin);
@@ -364,6 +352,14 @@ df_scan_alloc (bitmap all_blocks ATTRIBU
bb_info->artificial_uses = NULL;
}
+ if (! df_refs_obstack_is_init)
+ {
+ obstack_init (&df_refs_obstack);
+ df_refs_obstack_is_init = 1;
+ }
+ gcc_assert (df_first_refs_obj == NULL);
+ df_first_refs_obj = XOBNEW (&df_refs_obstack, void *);
+
bitmap_initialize (&df->hardware_regs_used, &problem_data->reg_bitmaps);
bitmap_initialize (&df->regular_block_artificial_uses, &problem_data->reg_bitmaps);
bitmap_initialize (&df->eh_block_artificial_uses, &problem_data->reg_bitmaps);
@@ -791,9 +787,15 @@ df_install_ref_incremental (df_ref ref)
}
ref_rec = *ref_rec_ptr;
+ /* fprintf (stderr, "count:%d ref_rec:%p\n", count, ref_rec); */
if (count)
{
- ref_rec = XRESIZEVEC (df_ref, ref_rec, count+2);
+ /* Impossible to actually know if ref_rec was malloc'ed or obstack'ed
+ thus we might have a leak here! */
+ df_ref *ref_rec2 = XOBNEWVEC (&df_refs_obstack, df_ref, count+2);
+ memcpy (ref_rec2, ref_rec, count*sizeof(df_ref));
+ /* free (ref_rec); */
+ ref_rec = ref_rec2;
*ref_rec_ptr = ref_rec;
ref_rec[count] = ref;
ref_rec[count+1] = NULL;
@@ -801,7 +803,7 @@ df_install_ref_incremental (df_ref ref)
}
else
{
- df_ref *ref_rec = XNEWVEC (df_ref, 2);
+ ref_rec = XOBNEWVEC (&df_refs_obstack, df_ref, 2);
ref_rec[0] = ref;
ref_rec[1] = NULL;
*ref_rec_ptr = ref_rec;
@@ -1070,8 +1072,9 @@ df_ref_chain_delete (df_ref *ref_rec)
/* If the list is empty, it has a special shared element that is not
to be deleted. */
- if (*start)
- free (start);
+ /* if (*start) */
+ /* free (start); */
+ /* obstack_free'd alltogether in the end of df pass. */
}
@@ -2611,7 +2615,7 @@ df_install_refs (basic_block bb,
count = VEC_length (df_ref, old_vec);
if (count)
{
- df_ref *new_vec = XNEWVEC (df_ref, count + 1);
+ df_ref *new_vec = XOBNEWVEC (&df_refs_obstack, df_ref, count + 1);
bool add_to_table;
df_ref this_ref;
unsigned int ix;
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [DF] RFC: obstacks in DF
2012-08-20 14:55 ` [DF] RFC: obstacks in DF Dimitrios Apostolou
@ 2012-08-20 15:32 ` Steven Bosscher
0 siblings, 0 replies; 24+ messages in thread
From: Steven Bosscher @ 2012-08-20 15:32 UTC (permalink / raw)
To: Dimitrios Apostolou
Cc: gcc-patches, Paolo Bonzini, Andrey Belevantsev, Michael Matz
On Mon, Aug 20, 2012 at 4:54 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
> In the process I realised that obstacks weren't exactly suitable (thanks
> matz for helping on IRC),
Right, alloc-pool would be a better choice here.
Ciao!
Steven
^ permalink raw reply [flat|nested] 24+ messages in thread
* failed attempt: retain identifier length from frontend to backend
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
` (7 preceding siblings ...)
2012-08-20 14:55 ` [DF] RFC: obstacks in DF Dimitrios Apostolou
@ 2012-08-20 17:04 ` Dimitrios Apostolou
2012-08-21 6:07 ` Richard Guenther
2012-08-24 16:12 ` Tom Tromey
8 siblings, 2 replies; 24+ messages in thread
From: Dimitrios Apostolou @ 2012-08-20 17:04 UTC (permalink / raw)
To: gcc-patches; +Cc: Andrey Belevantsev
Hello,
my last attempt on improving something serious was about three weeks ago,
trying to keep all lengths of all strings parsed in the frontend for the
whole compilation phase until the assembly output. I was hoping that would
help on using faster hashes (knowing the length allows us to hash 4 or 8
bytes per iteration), quicker strcmp in various places, and using less
strlen() calls, which show especially on -g3 compilations that store huge
macro strings.
I'll post no patch here, since what I currently have is a mess in 3
different branches and most don't even compile. I tried various
approaches. First I tried adding an extra length parameter in all relevant
functions, starting from the assembly generation and working my way
upwards. This got too complex, and I'd really like to ask if you find any
meaning in changing target specific hooks and macros to actually accept
length as argument (e.g. ASM_OUTPUT_*) or return it (e.g. ASM_GENERATE_*).
Changes seemed too intrusive for me to continue.
But seeing that identifier length is there inside struct ht_identifier (or
cpp_hashnode) and not lost, I tried the approach of having the length at
str[-4] for all identifiers. To achieve this I changed ht_identifier to
store str with the flexible array hack. Unfortunately I hadn't noticed
that ht_identifier was a part of tree_node and also part of too many other
structs, so changing all those structs to have variable size was not
without side effects. In the end it compiled but I got crashes all over,
and I'm sure I didn't do things right since I broke things like the static
assert in libcpp/identifiers.c, that I don't even understand:
/* We don't need a proxy since the hash table's identifier comes first
in cpp_hashnode. However, in case this is ever changed, we have a
static assertion for it. */
-extern char proxy_assertion_broken[offsetof (struct cpp_hashnode, ident) == 0 ? 1 : -1];
Anyway last attempt was to decouple ht_identifier completely from trees
and other structs by storing pointer to it, but I was pretty worn out and
quickly gave up after getting errors on gengtype-generated files that I
didn't even know how to handle.
Was all this project too ambitious? I'd appreciate all input.
Thanks,
Dimitris
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: failed attempt: retain identifier length from frontend to backend
2012-08-20 17:04 ` failed attempt: retain identifier length from frontend to backend Dimitrios Apostolou
@ 2012-08-21 6:07 ` Richard Guenther
2012-08-24 16:12 ` Tom Tromey
1 sibling, 0 replies; 24+ messages in thread
From: Richard Guenther @ 2012-08-21 6:07 UTC (permalink / raw)
To: Dimitrios Apostolou; +Cc: gcc-patches, Andrey Belevantsev
On Mon, Aug 20, 2012 at 7:03 PM, Dimitrios Apostolou <jimis@gmx.net> wrote:
> Hello,
>
> my last attempt on improving something serious was about three weeks ago,
> trying to keep all lengths of all strings parsed in the frontend for the
> whole compilation phase until the assembly output. I was hoping that would
> help on using faster hashes (knowing the length allows us to hash 4 or 8
> bytes per iteration), quicker strcmp in various places, and using less
> strlen() calls, which show especially on -g3 compilations that store huge
> macro strings.
>
> I'll post no patch here, since what I currently have is a mess in 3
> different branches and most don't even compile. I tried various approaches.
> First I tried adding an extra length parameter in all relevant functions,
> starting from the assembly generation and working my way upwards. This got
> too complex, and I'd really like to ask if you find any meaning in changing
> target specific hooks and macros to actually accept length as argument (e.g.
> ASM_OUTPUT_*) or return it (e.g. ASM_GENERATE_*). Changes seemed too
> intrusive for me to continue.
>
> But seeing that identifier length is there inside struct ht_identifier (or
> cpp_hashnode) and not lost, I tried the approach of having the length at
> str[-4] for all identifiers. To achieve this I changed ht_identifier to
> store str with the flexible array hack. Unfortunately I hadn't noticed that
> ht_identifier was a part of tree_node and also part of too many other
> structs, so changing all those structs to have variable size was not without
> side effects. In the end it compiled but I got crashes all over, and I'm
> sure I didn't do things right since I broke things like the static assert in
> libcpp/identifiers.c, that I don't even understand:
>
> /* We don't need a proxy since the hash table's identifier comes first
> in cpp_hashnode. However, in case this is ever changed, we have a
> static assertion for it. */
> -extern char proxy_assertion_broken[offsetof (struct cpp_hashnode, ident) ==
> 0 ? 1 : -1];
>
> Anyway last attempt was to decouple ht_identifier completely from trees and
> other structs by storing pointer to it, but I was pretty worn out and
> quickly gave up after getting errors on gengtype-generated files that I
> didn't even know how to handle.
>
> Was all this project too ambitious? I'd appreciate all input.
I think the proper thing would indeed have been to pass down the length of
the string to relevant functions.
Richard.
>
> Thanks,
> Dimitris
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Speedups/Cleanups: End of GSOC patch collection
2012-08-20 9:20 ` Dodji Seketeli
@ 2012-08-24 15:41 ` Tom Tromey
0 siblings, 0 replies; 24+ messages in thread
From: Tom Tromey @ 2012-08-24 15:41 UTC (permalink / raw)
To: Dodji Seketeli
Cc: Dimitrios Apostolou, gcc-patches, Andrey Belevantsev, Ian Lance Taylor
>>>>> "Dodji" == Dodji Seketeli <dodji@seketeli.org> writes:
Dodji> With these changes, the libcpp parts look OK to me if they still
Dodji> boostrap post c++ conversion. I am not a maintainer so I a deferring to
Dodji> Tom and the other maintainers.
I agree. Dodji, thanks for looking at this.
Dmitris, thanks for writing it -- patch ok with that change.
Tom
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: failed attempt: retain identifier length from frontend to backend
2012-08-20 17:04 ` failed attempt: retain identifier length from frontend to backend Dimitrios Apostolou
2012-08-21 6:07 ` Richard Guenther
@ 2012-08-24 16:12 ` Tom Tromey
1 sibling, 0 replies; 24+ messages in thread
From: Tom Tromey @ 2012-08-24 16:12 UTC (permalink / raw)
To: Dimitrios Apostolou; +Cc: gcc-patches, Andrey Belevantsev
>>>>> "Dimitris" == Dimitrios Apostolou <jimis@gmx.net> writes:
Dimitris> [...] since I broke things like the static assert in
Dimitris> libcpp/identifiers.c, that I don't even understand:
Dimitris> /* We don't need a proxy since the hash table's identifier comes first
Dimitris> in cpp_hashnode. However, in case this is ever changed, we have a
Dimitris> static assertion for it. */
Dimitris> -extern char proxy_assertion_broken[offsetof (struct cpp_hashnode, ident) == 0 ? 1 : -1];
This assertion is because the implementation of cpp_forall_identifiers
relies on the layout of cpp_hashnode:
void
cpp_forall_identifiers (cpp_reader *pfile, cpp_cb cb, void *v)
{
ht_forall (pfile->hash_table, (ht_cb) cb, v);
}
The idea is that since the identifier comes first, we can walk the hash
table directly using ht_forall, relying on an implicit cast to convert
the ht_identifier* to a cpp_hashnode*.
This is somewhat bogus -- casts of functions are almost never good.
(In gdb at least we tend to be more pedantic about this kind of thing.
But this code has been in libcpp a long time...)
If the struct were laid out differently, then cpp_forall_identifiers
would need an intermediate function to do the conversion and then call
'cb'.
Tom
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2012-08-24 16:12 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-18 11:19 Speedups/Cleanups: End of GSOC patch collection Dimitrios Apostolou
2012-08-18 11:50 ` Dimitrios Apostolou
2012-08-18 16:37 ` Dimitrios Apostolou
2012-08-20 9:20 ` Dodji Seketeli
2012-08-24 15:41 ` Tom Tromey
2012-08-18 18:10 ` [graphds.h] Allocate graph from obstack Dimitrios Apostolou
2012-08-19 16:55 ` Richard Guenther
2012-08-20 12:04 ` Paolo Bonzini
2012-08-20 12:17 ` Richard Guenther
2012-08-20 13:17 ` Dimitrios Apostolou
2012-08-18 19:10 ` more malloc mitigation Dimitrios Apostolou
2012-08-19 18:30 ` alloc_pool for tree-ssa-pre.c:phi_translate_table Dimitrios Apostolou
2012-08-20 7:38 ` Richard Guenther
2012-08-20 9:29 ` Jakub Jelinek
2012-08-20 9:37 ` Dimitrios Apostolou
2012-08-19 18:30 ` obstack for equiv_class_label, more vectors on stack Dimitrios Apostolou
2012-08-19 18:31 ` enlarge hot allocation pools Dimitrios Apostolou
2012-08-19 21:55 ` Steven Bosscher
2012-08-20 3:26 ` Dimitrios Apostolou
2012-08-20 14:55 ` [DF] RFC: obstacks in DF Dimitrios Apostolou
2012-08-20 15:32 ` Steven Bosscher
2012-08-20 17:04 ` failed attempt: retain identifier length from frontend to backend Dimitrios Apostolou
2012-08-21 6:07 ` Richard Guenther
2012-08-24 16:12 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).