public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* 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 ` obstack for equiv_class_label, more vectors on stack 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
                   ` (4 preceding siblings ...)
  2012-08-19 18:30 ` obstack for equiv_class_label, more vectors on stack Dimitrios Apostolou
@ 2012-08-19 18:30 ` Dimitrios Apostolou
  2012-08-20  7:38   ` Richard Guenther
  2012-08-19 18:31 ` enlarge hot allocation pools Dimitrios Apostolou
                   ` (2 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
                   ` (3 preceding siblings ...)
  2012-08-18 19:10 ` more malloc mitigation Dimitrios Apostolou
@ 2012-08-19 18:30 ` Dimitrios Apostolou
  2012-08-19 18:30 ` alloc_pool for tree-ssa-pre.c:phi_translate_table Dimitrios Apostolou
                   ` (3 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 ` alloc_pool for tree-ssa-pre.c:phi_translate_table 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 ` obstack for equiv_class_label, more vectors on stack 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: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).