===================================================================
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3.
#include "gimple.h"
#include "tree-ssa-alias.h"
#include "plugin.h"
+#include "tree-pass.h"
#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
#include "dbxout.h"
@@ -1783,6 +1784,7 @@ dump_memory_report (bool final)
dump_ggc_loc_statistics (final);
dump_alias_stats (stderr);
dump_pta_stats (stderr);
+ dump_pass_memory_stats (stderr);
}
/* Clean up: close opened files, etc. */
@@ -1868,7 +1870,9 @@ do_compile (void)
init_cgraph ();
init_final (main_input_filename);
coverage_init (aux_base_name);
- statistics_init ();
+ statistics_init ();
+ if (mem_report)
+ instrument_malloc ();
invoke_plugin_callbacks (PLUGIN_START_UNIT, NULL);
timevar_stop (TV_PHASE_SETUP);
===================================================================
@@ -78,6 +78,11 @@ struct opt_pass
/* Flags indicating common sets things to do before and after. */
unsigned int todo_flags_start;
unsigned int todo_flags_finish;
+
+ size_t alloc_cnt;
+ size_t alloc_sum;
+ size_t alloc_curr;
+ size_t alloc_peak;
};
/* Description of GIMPLE pass. */
@@ -557,4 +562,7 @@ extern void disable_pass (const char *);
extern void enable_pass (const char *);
extern void dump_passes (void);
+extern void instrument_malloc (void);
+extern void dump_pass_memory_stats (FILE *);
+
#endif /* GCC_TREE_PASS_H */
===================================================================
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.
#include "config.h"
#include "system.h"
+#include <malloc.h>
#include "coretypes.h"
#include "tm.h"
#include "line-map.h"
@@ -105,6 +106,158 @@ bool in_gimple_form;
bool first_pass_instance;
+struct malloc_chunk_head {
+ size_t x;
+ size_t size;
+};
+typedef struct malloc_chunk_head* mchunkptr;
+#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*sizeof(size_t)))
+
+static void (*gcc_old_free_hook) (void *ptr, const void *);
+static void *(*gcc_old_malloc_hook) (size_t size, const void *);
+static void *(*gcc_old_realloc_hook) (void *ptr, size_t size, const void *);
+
+static void *gcc_malloc_hook (size_t size, const void *caller);
+static void *gcc_realloc_hook (void *ptr, size_t size, const void *caller);
+static void gcc_free_hook (void *ptr, const void *caller);
+
+struct opt_pass mem_overall;
+struct opt_pass mem_rest_of_comp;
+
+static void *
+gcc_malloc_hook (size_t size, const void *caller)
+{
+ void *res;
+ __malloc_hook = gcc_old_malloc_hook;
+ __realloc_hook = gcc_old_realloc_hook;
+ __free_hook = gcc_old_free_hook;
+ if (gcc_old_malloc_hook != NULL)
+ res = gcc_old_malloc_hook (size, caller);
+ else
+ res = xmalloc (size);
+ __malloc_hook = gcc_malloc_hook;
+ __realloc_hook = gcc_realloc_hook;
+ __free_hook = gcc_free_hook;
+ struct opt_pass *p = current_pass ? current_pass : &mem_rest_of_comp;
+ /* The allocator allocates a chunk >= size. */
+ size = res ? mem2chunk (res)->size : 0;
+ p->alloc_cnt++;
+ p->alloc_sum += size;
+ p->alloc_curr += size;
+ if ((ssize_t) p->alloc_curr > (ssize_t) p->alloc_peak)
+ p->alloc_peak = p->alloc_curr;
+ mem_overall.alloc_cnt++;
+ mem_overall.alloc_sum += size;
+ mem_overall.alloc_curr += size;
+ if ((ssize_t) mem_overall.alloc_curr > (ssize_t) mem_overall.alloc_peak)
+ mem_overall.alloc_peak = mem_overall.alloc_curr;
+ return res;
+}
+
+static void *
+gcc_realloc_hook (void *ptr, size_t size, const void *caller)
+{
+ size_t oldsize = ptr ? mem2chunk (ptr)->size : 0;
+ void *res;
+ __malloc_hook = gcc_old_malloc_hook;
+ __realloc_hook = gcc_old_realloc_hook;
+ __free_hook = gcc_old_free_hook;
+ if (gcc_old_realloc_hook != NULL)
+ res = gcc_old_realloc_hook (ptr, size, caller);
+ else
+ res = xrealloc (ptr, size);
+ __malloc_hook = gcc_malloc_hook;
+ __realloc_hook = gcc_realloc_hook;
+ __free_hook = gcc_free_hook;
+ struct opt_pass *p = current_pass ? current_pass : &mem_rest_of_comp;
+ /* The allocator allocates a chunk >= size. */
+ size = res ? mem2chunk (res)->size : 0;
+ p->alloc_cnt++;
+ p->alloc_sum += (size - oldsize);
+ p->alloc_curr += (size - oldsize);
+ if ((ssize_t) p->alloc_curr > (ssize_t) p->alloc_peak)
+ p->alloc_peak = p->alloc_curr;
+ mem_overall.alloc_cnt++;
+ mem_overall.alloc_sum += (size - oldsize);
+ mem_overall.alloc_curr += (size - oldsize);
+ if ((ssize_t) mem_overall.alloc_curr > (ssize_t) mem_overall.alloc_peak)
+ mem_overall.alloc_peak = mem_overall.alloc_curr;
+ return res;
+}
+
+static void
+gcc_free_hook (void *ptr, const void *caller)
+{
+ struct opt_pass *p = current_pass ? current_pass : &mem_rest_of_comp;
+ size_t size = ptr ? mem2chunk (ptr)->size : 0;
+ p->alloc_curr -= size;
+ mem_overall.alloc_curr -= size;
+ __malloc_hook = gcc_old_malloc_hook;
+ __realloc_hook = gcc_old_realloc_hook;
+ __free_hook = gcc_old_free_hook;
+ if (gcc_old_free_hook != NULL)
+ gcc_old_free_hook (ptr, caller);
+ else
+ free (ptr);
+ __malloc_hook = gcc_malloc_hook;
+ __realloc_hook = gcc_realloc_hook;
+ __free_hook = gcc_free_hook;
+}
+
+static void
+dump_pass_memory_stats_1 (FILE *file, struct opt_pass *pass)
+{
+ do
+ {
+ if (pass->sub)
+ dump_pass_memory_stats_1 (file, pass->sub);
+
+ if (pass->alloc_cnt != 0
+ || pass->alloc_curr != 0)
+ {
+ fprintf (file, "%.14s:", pass->name);
+ if (strlen (pass->name) < 7)
+ fprintf (file, "\t");
+ fprintf (file, "\t%zd\t%zd\t%zd\t%zd\n",
+ pass->alloc_cnt,
+ pass->alloc_sum / 1024, ((ssize_t) pass->alloc_curr) / 1024,
+ pass->alloc_peak / 1024);
+ }
+ pass = pass->next;
+ }
+ while (pass);
+}
+
+void
+dump_pass_memory_stats (FILE *file)
+{
+ fprintf (file, "\n\nPer pass non-gc memory allocation stats\n\n");
+ fprintf (file, "Pass\t\t Cnt\t Total kB\t Leak kB\t Peak kB\n");
+ mem_rest_of_comp.name = "(no pass)";
+ dump_pass_memory_stats_1 (file, &mem_rest_of_comp);
+ dump_pass_memory_stats_1 (file, all_lowering_passes);
+ dump_pass_memory_stats_1 (file, all_small_ipa_passes);
+ dump_pass_memory_stats_1 (file, all_regular_ipa_passes);
+ dump_pass_memory_stats_1 (file, all_lto_gen_passes);
+ dump_pass_memory_stats_1 (file, all_late_ipa_passes);
+ dump_pass_memory_stats_1 (file, all_passes);
+ mem_overall.name = "TOTAL";
+ dump_pass_memory_stats_1 (file, &mem_overall);
+ fprintf (file, "\n");
+}
+
+void
+instrument_malloc (void)
+{
+ gcc_old_malloc_hook = __malloc_hook;
+ __malloc_hook = gcc_malloc_hook;
+ gcc_old_free_hook = __free_hook;
+ __free_hook = gcc_free_hook;
+ gcc_old_realloc_hook = __realloc_hook;
+ __realloc_hook = gcc_realloc_hook;
+}
+
+
/* This is called from various places for FUNCTION_DECL, VAR_DECL,
and TYPE_DECL nodes.
@@ -1965,6 +2118,9 @@ execute_function_todo (void *data)
}
else if (flags & TODO_verify_stmts)
verify_gimple_in_cfg (cfun);
+ if (current_loops
+ && cfun->curr_properties & PROP_loops)
+ verify_loop_structure ();
if (flags & TODO_verify_flow)
verify_flow_info ();
if (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA))