[RFC/RFA?] Per call memory garbage statistics
Jan Hubicka
jh@suse.cz
Wed Jan 21 19:47:00 GMT 2004
Hi,
this is the per-call memory statistics patch I was playing around last two
days. It looks like it is quite usefull as it shown quite many problems
already. The output looks (in my current tree) like this:
source location Times Allocated Overhead
-------------------------------------------------------
[snip]
stmt.c:2389 (expand_end_stmt_expr) 33128 662560 0:0.218%
cp/lex.c:818 (cxx_make_type) 5236 565488 104720:0.221%
tree.c:2540 (build_nt) 31785 688472 0:0.227%
cp/decl.c:540 (poplevel) 18230 729200 0:0.240%
cgraph.c:157 (create_edge) 37900 758000 0:0.250%
rtl.c:158 (rtvec_alloc) 61915 769988 1288:0.254%
tree.c:391 (copy_list) 7837 832844 0:0.274%
cgraph.c:113 (cgraph_node) 6155 664740 172340:0.276%
cp/decl.c:10519 (save_function_data) 7036 759888 112576:0.287%
tree.c:387 (copy_list) 8219 880964 0:0.290%
emit-rtl.c:316 (get_mem_attrs) 44805 896100 0:0.295%
cp/name-lookup.c:4699 (maybe_push_to_top_level) 7726 834408 61808:0.295%
convert.c:371 (convert_to_integer) 45763 915260 0:0.301%
tree.c:3645 (build_pointer_type_for_mode) 7241 782028 144820:0.305%
stringpool.c:70 (alloc_node) 14308 915712 57232:0.320%
cp/tree.c:252 (build_local_temp) 9059 978372 0:0.322%
cp/decl.c:10239 (start_function) 9156 988848 0:0.326%
genrtl.c:688 (gen_rtx_fmt_u00) 62462 999392 0:0.329%
cp/call.c:2505 (build_user_type_conversion_1) 51146 1022920 0:0.337%
cp/call.c:2499 (build_user_type_conversion_1) 51146 1022920 0:0.337%
genrtl.c:236 (gen_rtx_fmt_e) 131307 1050456 0:0.346%
tree.c:2943 (build_type_copy) 8368 903744 167360:0.353%
tree-inline.c:1367 (expand_call_inline) 54498 1089960 0:0.359%
emit-rtl.c:367 (get_reg_attrs) 91169 1094028 0:0.360%
cp/lex.c:810 (copy_type) 8629 931932 172580:0.364%
stmt.c:3451 (expand_start_bindings_and_block) 56531 1130620 0:0.372%
cp/decl.c:11188 (cxx_push_function_context) 9158 989064 146528:0.374%
cp/lex.c:756 (cxx_dup_lang_specific_decl) 29291 1168644 0:0.385%
stmt.c:2344 (expand_start_stmt_expr) 33128 1060096 132512:0.393%
cp/pt.c:9288 (try_class_unification) 52677 1212648 18352:0.405%
except.c:463 (init_eh_for_function) 9158 989064 256424:0.410%
cp/name-lookup.c:4178 (arg_assoc_class) 64671 1293420 0:0.426%
cp/tree.c:912 (ovl_cons) 85443 1367088 0:0.450%
cp/call.c:2527 (build_user_type_conversion_1) 68972 1379440 0:0.454%
tree.c:2606 (build_expr_wfl) 41763 1336416 167052:0.495%
cp/parser.c:356 (cp_lexer_new_from_tokens) 2401 1205708 364476:0.517%
cp/parser.c:145 (cp_token_cache_push_token) 3193 1634816 12772:0.543%
tree.c:408 (build_int_2_wide) 83583 1671660 0:0.551%
cp/lex.c:700 (build_lang_decl) 15711 1696788 0:0.559%
cp/call.c:1103 (reference_binding) 85698 1713960 0:0.565%
cp/decl2.c:186 (cp_build_parm_decl) 16118 1740744 0:0.573%
cp/call.c:2161 (add_template_candidate_real) 95347 2324284 63336:0.786%
tree-inline.c:349 (remap_block) 66483 2659320 0:0.876%
tree.c:2317 (build) 113068 2784040 18836:0.923%
tree-inline.c:1443 (expand_call_inline) 27249 2942892 0:0.969%
ggc-common.c:188 (ggc_calloc) 1512 2946444 13692:0.975%
cp/name-lookup.c:1709 (set_identifier_type_value_with_scope) 151575 3031500 0:0.998%
varray.c:128 (varray_init) 27212 2344308 707908:1.005%
tree.c:3923 (build_method_type_directly) 24117 2604636 482340:1.017%
genrtl.c:478 (gen_rtx_fmt_iuuB00is) 72608 2904320 290432:1.052%
cp/lex.c:773 (copy_decl) 31555 3407940 0:1.122%
cp/name-lookup.c:2786 (push_class_level_binding) 170972 3419440 0:1.126%
combine.c:9886 (recog_for_combine) 73864 3313984 299520:1.190%
genrtl.c:635 (gen_rtx_fmt_i00) 233298 3732768 0:1.229%
cp/search.c:1200 (build_baselink) 167695 4024680 0:1.326%
cp/pt.c:6158 (tsubst_decl) 38660 4175280 0:1.375%
cselib.c:831 (cselib_subst_to_values) 357657 4258224 0:1.403%
cp/name-lookup.c:4675 (store_bindings) 221612 4432240 0:1.460%
genrtl.c:51 (gen_rtx_fmt_ue) 374279 4491348 0:1.479%
cp/call.c:1312 (add_function_candidate) 206354 4591208 9876:1.515%
cp/call.c:610 (standard_conversion) 244350 4887000 0:1.610%
genrtl.c:671 (gen_rtx_fmt_e0) 429635 5155620 0:1.698%
c-semantics.c:200 (build_stmt) 263496 5325244 12588:1.758%
genrtl.c:619 (gen_rtx_fmt_0) 703683 5629464 0:1.854%
integrate.c:373 (copy_decl_for_inlining) 52222 5639976 0:1.858%
integrate.c:357 (copy_decl_for_inlining) 54463 5882004 0:1.937%
cp/call.c:543 (build_conv) 295266 5922884 0:1.951%
cp/pt.c:5647 (tsubst_template_args) 244762 5883460 73716:1.962%
varray.c:161 (varray_grow) 22435 4472692 1830136:2.076%
cp/pt.c:3755 (coerce_template_parms) 279266 6572008 64732:2.186%
function.c:6384 (allocate_struct_function) 9158 4688896 1978128:2.196%
rtl.c:246 (copy_rtx) 580407 6967440 0:2.295%
tree.c:3869 (build_function_type) 57823 6244884 1156460:2.438%
cp/call.c:1261 (add_candidate) 206686 8267440 0:2.723%
stmt.c:3406 (expand_start_bindings_and_block) 129461 8285504 0:2.729%
genrtl.c:33 (gen_rtx_fmt_ee) 1095450 13145400 0:4.330%
emit-rtl.c:3474 (get_new_any_insn) 432335 14514808 188000:4.843%
tree-inline.c:1986 (copy_tree_r) 2099693 43079168 117801:14.228%
Total 12229041 293366904 10246871
-------------------------------------------------------
The RTL expanders and build function needs ot be transparentized, but otherwise
I think it makes it quite easy to see where the memory is going (I've cut it
down from 480MB total to 293MB you can see in my log in two days quite easilly)
Would be something liket this acceptable for mainlnie?
Honza
* ggc-common.c (ggc_alloc_cleared_stat, ggc_realloc_stat):
Rename from ...; make statistics transparent.
(ggc_alloc_cleared, ggc_realloc_stat): ... these.
(loc_descriptor): New structure.
(hash_descriptor, eq_descriptor, loc_descriptor, cmp_statistics,
add_statistics):
New static function.
(ggc_record_overhead, dump_statistics): New global function.
* ggc-none.c (ggc_alloc_types_stat, ggc_alloc_stat, ggc_alloc_zone_stat,
ggc_alloc_cleared_stat, ggc_realloc_stat, ggc_alloc_typed_stat): Rename
from ...; accept locations
(ggc_alloc_types, ggc_alloc, ggc_alloc_zone, ggc_alloc_cleared,
ggc_realloc, ggc_alloc_typed): ... this one.
from ...; accept locations
* ggc-page.c (ggc_alloc_typed_stat, ggc_alloc_zone_stat,
ggc_alloc_stat): Rename from ... ; pass locations
* ggc-page.c (ggc_alloc_typed, ggc_alloc_zone, ggc_alloc):
... this one.
(ggc_alloc_stat): Record overehead.
* ggc.h (ggc_alloc_types, ggc_alloc, ggc_alloc_zone, ggc_alloc_cleared,
ggc_realloc, ggc_alloc_typed): Turn to macros
(ggc_alloc_types_stat, ggc_alloc_stat, ggc_alloc_zone_stat,
ggc_alloc_cleared_stat, ggc_realloc_stat, ggc_alloc_typed_stat): Declare.
(dump_ggc_loc_satistics, ggc_record_overehead): Declare.
* langhooks.h (lhd_make_node): Declare.
(LANG_HOOKS_MAKE_TYPE): Default to new function,
* langhooks.c (lhd_make_node): New.
* rtl.c (rtx_alloc_stat, swallow_copy_rtx_stat): Rename from ... ; pass
locations.
(rtx_alloc, swallow_copy_rtx): ... this one.
* rtl.h (rtx_alloc, swallow_copy_rtx): Turn to macros.
* rtl.c (rtx_alloc_stat, swallow_copy_rtx_stat): Declare.
* toplpev.c (finalize): Dump stats.
* tree.c (make_node_stat, copy_node_stat, make_tree_vec_stat,
build_tree_list_stat, tree_cons_stat, build1_stat, build_decl_stat):
Rename from ... ; pass locators.
(make_node, copy_node, make_tree_vec, build_tree_list, tree_cons,
build1, build_decl): Declare.
* tree.h (make_node_stat, copy_node_stat, make_tree_vec_stat,
build_tree_list_stat, tree_cons_stat, build1_stat, build_decl_stat):
Declare.
(make_node, copy_node, make_tree_vec, build_tree_list, tree_cons,
build1, build_decl): New macros.
* Makefile.in (RTL_H, TREE_H): Add statistics.h dependency.
* statistics.h: New file.
Index: ggc-none.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc-none.c,v
retrieving revision 1.15
diff -c -3 -p -r1.15 ggc-none.c
*** ggc-none.c 27 Oct 2003 00:26:52 -0000 1.15
--- ggc-none.c 21 Jan 2004 18:24:29 -0000
*************** struct alloc_zone *rtl_zone = NULL;
*** 32,62 ****
struct alloc_zone *garbage_zone = NULL;
void *
! ggc_alloc_typed (enum gt_types_enum gte ATTRIBUTE_UNUSED, size_t size)
{
return xmalloc (size);
}
void *
! ggc_alloc (size_t size)
{
return xmalloc (size);
}
void *
! ggc_alloc_zone (size_t size, struct alloc_zone *zone ATTRIBUTE_UNUSED)
{
return xmalloc (size);
}
void *
! ggc_alloc_cleared (size_t size)
{
return xcalloc (size, 1);
}
void *
! ggc_realloc (void *x, size_t size)
{
return xrealloc (x, size);
}
--- 32,64 ----
struct alloc_zone *garbage_zone = NULL;
void *
! ggc_alloc_typed_stat (enum gt_types_enum gte ATTRIBUTE_UNUSED, size_t size
! MEM_STAT_DECL)
{
return xmalloc (size);
}
void *
! ggc_alloc_stat (size_t size MEM_STAT_DECL)
{
return xmalloc (size);
}
void *
! ggc_alloc_zone_stat (size_t size, struct alloc_zone *zone ATTRIBUTE_UNUSED
! MEM_STAT_DECL)
{
return xmalloc (size);
}
void *
! ggc_alloc_cleared_stat (size_t size MEM_STAT_DECL)
{
return xcalloc (size, 1);
}
void *
! ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
{
return xrealloc (x, size);
}
Index: ggc-page.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc-page.c,v
retrieving revision 1.84
diff -c -3 -p -r1.84 ggc-page.c
*** ggc-page.c 22 Dec 2003 07:42:37 -0000 1.84
--- ggc-page.c 21 Jan 2004 18:24:35 -0000
*************** static unsigned char size_lookup[257] =
*** 1031,1053 ****
/* Typed allocation function. Does nothing special in this collector. */
void *
! ggc_alloc_typed (enum gt_types_enum type ATTRIBUTE_UNUSED, size_t size)
{
! return ggc_alloc (size);
}
/* Zone allocation function. Does nothing special in this collector. */
void *
! ggc_alloc_zone (size_t size, struct alloc_zone *zone ATTRIBUTE_UNUSED)
{
! return ggc_alloc (size);
}
/* Allocate a chunk of memory of SIZE bytes. Its contents are undefined. */
void *
! ggc_alloc (size_t size)
{
unsigned order, word, bit, object_offset;
struct page_entry *entry;
--- 1031,1055 ----
/* Typed allocation function. Does nothing special in this collector. */
void *
! ggc_alloc_typed_stat (enum gt_types_enum type ATTRIBUTE_UNUSED, size_t size
! MEM_STAT_DECL)
{
! return ggc_alloc_stat (size PASS_MEM_STAT);
}
/* Zone allocation function. Does nothing special in this collector. */
void *
! ggc_alloc_zone_stat (size_t size, struct alloc_zone *zone ATTRIBUTE_UNUSED
! MEM_STAT_DECL)
{
! return ggc_alloc_stat (size PASS_MEM_STAT);
}
/* Allocate a chunk of memory of SIZE bytes. Its contents are undefined. */
void *
! ggc_alloc_stat (size_t size MEM_STAT_DECL)
{
unsigned order, word, bit, object_offset;
struct page_entry *entry;
*************** ggc_alloc (size_t size)
*** 1191,1196 ****
--- 1193,1199 ----
G.stats.total_overhead_under128 += OBJECT_SIZE (order) - size;
G.stats.total_allocated_under128 += OBJECT_SIZE(order);
}
+ ggc_record_overhead (OBJECT_SIZE (order), OBJECT_SIZE (order) - size PASS_MEM_STAT);
}
#endif
Index: ggc.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc.h,v
retrieving revision 1.61
diff -c -3 -p -r1.61 ggc.h
*** ggc.h 21 Dec 2003 14:08:33 -0000 1.61
--- ggc.h 21 Jan 2004 18:24:36 -0000
*************** Software Foundation, 59 Temple Place - S
*** 21,26 ****
--- 21,27 ----
#ifndef GCC_GGC_H
#define GCC_GGC_H
+ #include "statistics.h"
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
*************** extern struct alloc_zone *rtl_zone;
*** 210,228 ****
extern struct alloc_zone *tree_zone;
/* The internal primitive. */
! extern void *ggc_alloc (size_t);
/* Allocate an object into the specified allocation zone. */
! extern void *ggc_alloc_zone (size_t, struct alloc_zone *);
/* Allocate an object of the specified type and size. */
! extern void *ggc_alloc_typed (enum gt_types_enum, size_t);
/* Like ggc_alloc, but allocates cleared memory. */
! extern void *ggc_alloc_cleared (size_t);
/* Like ggc_alloc_zone, but allocates cleared memory. */
! extern void *ggc_alloc_cleared_zone (size_t, struct alloc_zone *);
/* Resize a block. */
! extern void *ggc_realloc (void *, size_t);
/* Like ggc_alloc_cleared, but performs a multiplication. */
extern void *ggc_calloc (size_t, size_t);
#define ggc_alloc_rtx(CODE) \
((rtx) ggc_alloc_typed (gt_ggc_e_7rtx_def, RTX_SIZE (CODE)))
--- 211,239 ----
extern struct alloc_zone *tree_zone;
/* The internal primitive. */
! extern void *ggc_alloc_stat (size_t MEM_STAT_DECL);
! #define ggc_alloc(s) ggc_alloc_stat (s MEM_STAT_INFO)
/* Allocate an object into the specified allocation zone. */
! extern void *ggc_alloc_zone_stat (size_t, struct alloc_zone * MEM_STAT_DECL);
! #define ggc_alloc_zone(s,z) ggc_alloc_zone_stat (s,z MEM_STAT_INFO)
/* Allocate an object of the specified type and size. */
! extern void *ggc_alloc_typed_stat (enum gt_types_enum, size_t MEM_STAT_DECL);
! #define ggc_alloc_typed(s,z) ggc_alloc_typed_stat (s,z MEM_STAT_INFO)
/* Like ggc_alloc, but allocates cleared memory. */
! extern void *ggc_alloc_cleared_stat (size_t MEM_STAT_DECL);
! #define ggc_alloc_cleared(s) ggc_alloc_cleared_stat (s MEM_STAT_INFO)
/* Like ggc_alloc_zone, but allocates cleared memory. */
! extern void *ggc_alloc_cleared_zone (size_t, struct alloc_zone * MEM_STAT_DECL);
! #define ggc_alloc_cleared_zone(s,z) ggc_alloc_cleared_stat (s,z MEM_STAT_INFO)
/* Resize a block. */
! extern void *ggc_realloc_stat (void *, size_t MEM_STAT_DECL);
! #define ggc_realloc(s,z) ggc_realloc_stat (s,z MEM_STAT_INFO)
/* Like ggc_alloc_cleared, but performs a multiplication. */
extern void *ggc_calloc (size_t, size_t);
+
+ extern void ggc_record_overhead (size_t, size_t MEM_STAT_DECL);
+
+ extern void dump_ggc_loc_statistics (void);
#define ggc_alloc_rtx(CODE) \
((rtx) ggc_alloc_typed (gt_ggc_e_7rtx_def, RTX_SIZE (CODE)))
Index: langhooks-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks-def.h,v
retrieving revision 1.71
diff -c -3 -p -r1.71 langhooks-def.h
*** langhooks-def.h 9 Jan 2004 19:54:59 -0000 1.71
--- langhooks-def.h 21 Jan 2004 18:24:48 -0000
*************** extern tree lhd_callgraph_analyze_expr (
*** 206,211 ****
--- 206,212 ----
/* Tree dump hooks. */
extern bool lhd_tree_dump_dump_tree (void *, tree);
extern int lhd_tree_dump_type_quals (tree);
+ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN lhd_tree_dump_dump_tree
#define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN lhd_tree_dump_type_quals
*************** extern int lhd_tree_dump_type_quals (tre
*** 217,223 ****
/* Types hooks. There are no reasonable defaults for most of them,
so we create a compile-time error instead. */
! #define LANG_HOOKS_MAKE_TYPE make_node
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
#define LANG_HOOKS_TYPE_PROMOTES_TO lhd_type_promotes_to
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type
--- 218,224 ----
/* Types hooks. There are no reasonable defaults for most of them,
so we create a compile-time error instead. */
! #define LANG_HOOKS_MAKE_TYPE lhd_make_node
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
#define LANG_HOOKS_TYPE_PROMOTES_TO lhd_type_promotes_to
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type
Index: langhooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks.c,v
retrieving revision 1.57
diff -c -3 -p -r1.57 langhooks.c
*** langhooks.c 9 Jan 2004 19:55:00 -0000 1.57
--- langhooks.c 21 Jan 2004 18:24:49 -0000
*************** lhd_callgraph_analyze_expr (tree *tp ATT
*** 562,565 ****
--- 562,571 ----
return NULL;
}
+ tree
+ lhd_make_node (enum tree_code code)
+ {
+ return make_node (code);
+ }
+
#include "gt-langhooks.h"
Index: rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.c,v
retrieving revision 1.130
diff -c -3 -p -r1.130 rtl.c
*** rtl.c 22 Dec 2003 07:42:37 -0000 1.130
--- rtl.c 21 Jan 2004 18:26:19 -0000
*************** rtvec_alloc (int n)
*** 173,183 ****
all the rest is initialized to zero. */
rtx
! rtx_alloc (RTX_CODE code)
{
rtx rt;
! rt = ggc_alloc_rtx (code);
/* We want to clear everything up to the FLD array. Normally, this
is one int, but we don't want to assume that and it isn't very
--- 173,183 ----
all the rest is initialized to zero. */
rtx
! rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL)
{
rtx rt;
! rt = ggc_alloc_typed_stat (gt_ggc_e_7rtx_def, RTX_SIZE (code) PASS_MEM_STAT);
/* We want to clear everything up to the FLD array. Normally, this
is one int, but we don't want to assume that and it isn't very
*************** copy_rtx (rtx orig)
*** 305,315 ****
/* Create a new copy of an rtx. Only copy just one level. */
rtx
! shallow_copy_rtx (rtx orig)
{
rtx copy;
! copy = ggc_alloc_rtx (GET_CODE (orig));
memcpy (copy, orig, RTX_SIZE (GET_CODE (orig)));
return copy;
}
--- 305,316 ----
/* Create a new copy of an rtx. Only copy just one level. */
rtx
! shallow_copy_rtx_stat (rtx orig MEM_STAT_DECL)
{
rtx copy;
! copy = ggc_alloc_typed_stat (gt_ggc_e_7rtx_def, RTX_SIZE (GET_CODE (orig))
! PASS_MEM_STAT);
memcpy (copy, orig, RTX_SIZE (GET_CODE (orig)));
return copy;
}
index: rtl.h
===================================================================
rcs file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.449
diff -c -3 -p -r1.449 rtl.h
*** rtl.h 17 jan 2004 22:14:17 -0000 1.449
--- rtl.h 21 jan 2004 18:26:26 -0000
*************** Software Foundation, 59 Temple Place - S
*** 21,26 ****
--- 21,27 ----
#ifndef GCC_RTL_H
#define GCC_RTL_H
+ #include "statistics.h"
struct function;
*************** extern rtx emit_copy_of_insn_after (rtx,
*** 1452,1460 ****
extern void set_reg_attrs_from_mem (rtx, rtx);
extern void set_mem_attrs_from_reg (rtx, rtx);
extern void set_reg_attrs_for_parm (rtx, rtx);
/* In rtl.c */
! extern rtx rtx_alloc (RTX_CODE);
extern rtvec rtvec_alloc (int);
extern rtx copy_rtx (rtx);
extern void dump_rtx_statistics (void);
--- 1458,1469 ----
extern void set_reg_attrs_from_mem (rtx, rtx);
extern void set_mem_attrs_from_reg (rtx, rtx);
extern void set_reg_attrs_for_parm (rtx, rtx);
+ extern void set_reg_pointer_align (rtx, unsigned int);
/* In rtl.c */
! extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
! #define rtx_alloc(c) rtx_alloc_stat (c MEM_STAT_INFO)
!
extern rtvec rtvec_alloc (int);
extern rtx copy_rtx (rtx);
extern void dump_rtx_statistics (void);
*************** extern rtx copy_rtx_if_shared (rtx);
*** 1464,1470 ****
/* In rtl.c */
extern rtx copy_most_rtx (rtx, rtx);
! extern rtx shallow_copy_rtx (rtx);
extern int rtx_equal_p (rtx, rtx);
/* In emit-rtl.c */
--- 1473,1480 ----
/* In rtl.c */
extern rtx copy_most_rtx (rtx, rtx);
! extern rtx shallow_copy_rtx_stat (rtx MEM_STAT_DECL);
! #define shallow_copy_rtx(a) shallow_copy_rtx_stat (a MEM_STAT_INFO)
extern int rtx_equal_p (rtx, rtx);
/* In emit-rtl.c */
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.865
diff -c -3 -p -r1.865 toplev.c
*** toplev.c 17 Jan 2004 12:28:57 -0000 1.865
--- toplev.c 21 Jan 2004 18:26:43 -0000
*************** finalize (void)
*** 4583,4588 ****
--- 4585,4592 ----
stringpool_statistics ();
dump_tree_statistics ();
dump_rtx_statistics ();
+ dump_varray_statistics ();
+ dump_ggc_loc_statistics ();
}
/* Free up memory for the benefit of leak detectors. */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.342
diff -c -3 -p -r1.342 tree.c
*** tree.c 16 Jan 2004 07:20:28 -0000 1.342
--- tree.c 21 Jan 2004 18:26:56 -0000
*************** tree_size (tree node)
*** 202,208 ****
Achoo! I got a code in the node. */
tree
! make_node (enum tree_code code)
{
tree t;
int type = TREE_CODE_CLASS (code);
--- 202,208 ----
Achoo! I got a code in the node. */
tree
! make_node_stat (enum tree_code code MEM_STAT_DECL)
{
tree t;
int type = TREE_CODE_CLASS (code);
*************** make_node (enum tree_code code)
*** 271,277 ****
tree_node_sizes[(int) kind] += length;
#endif
! t = ggc_alloc_tree (length);
memset (t, 0, length);
--- 271,277 ----
tree_node_sizes[(int) kind] += length;
#endif
! t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
memset (t, 0, length);
*************** make_node (enum tree_code code)
*** 342,355 ****
TREE_CHAIN is zero and it has a fresh uid. */
tree
! copy_node (tree node)
{
tree t;
enum tree_code code = TREE_CODE (node);
size_t length;
length = tree_size (node);
! t = ggc_alloc_tree (length);
memcpy (t, node, length);
TREE_CHAIN (t) = 0;
--- 342,355 ----
TREE_CHAIN is zero and it has a fresh uid. */
tree
! copy_node_stat (tree node MEM_STAT_DECL)
{
tree t;
enum tree_code code = TREE_CODE (node);
size_t length;
length = tree_size (node);
! t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
memcpy (t, node, length);
TREE_CHAIN (t) = 0;
*************** build_complex (tree type, tree real, tre
*** 569,575 ****
/* Build a newly constructed TREE_VEC node of length LEN. */
tree
! make_tree_vec (int len)
{
tree t;
int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
--- 569,575 ----
/* Build a newly constructed TREE_VEC node of length LEN. */
tree
! make_tree_vec_stat (int len MEM_STAT_DECL)
{
tree t;
int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
*************** make_tree_vec (int len)
*** 579,587 ****
tree_node_sizes[(int) vec_kind] += length;
#endif
! t = ggc_alloc_tree (length);
memset (t, 0, length);
TREE_SET_CODE (t, TREE_VEC);
TREE_VEC_LENGTH (t) = len;
--- 579,588 ----
tree_node_sizes[(int) vec_kind] += length;
#endif
! t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
memset (t, 0, length);
+
TREE_SET_CODE (t, TREE_VEC);
TREE_VEC_LENGTH (t) = len;
*************** nreverse (tree t)
*** 1039,1047 ****
purpose and value fields are PARM and VALUE. */
tree
! build_tree_list (tree parm, tree value)
{
! tree t = make_node (TREE_LIST);
TREE_PURPOSE (t) = parm;
TREE_VALUE (t) = value;
return t;
--- 1040,1048 ----
purpose and value fields are PARM and VALUE. */
tree
! build_tree_list_stat (tree parm, tree value MEM_STAT_DECL)
{
! tree t = make_node_stat (TREE_LIST PASS_MEM_STAT);
TREE_PURPOSE (t) = parm;
TREE_VALUE (t) = value;
return t;
*************** build_tree_list (tree parm, tree value)
*** 1052,1062 ****
and whose TREE_CHAIN is CHAIN. */
tree
! tree_cons (tree purpose, tree value, tree chain)
{
tree node;
! node = ggc_alloc_tree (sizeof (struct tree_list));
memset (node, 0, sizeof (struct tree_common));
--- 1053,1064 ----
and whose TREE_CHAIN is CHAIN. */
tree
! tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
{
tree node;
! node = ggc_alloc_zone_stat (sizeof (struct tree_list),
! tree_zone PASS_MEM_STAT);
memset (node, 0, sizeof (struct tree_common));
*************** build (enum tree_code code, tree tt, ...
*** 2416,2422 ****
of varargs, which is expensive for RISC machines. */
tree
! build1 (enum tree_code code, tree type, tree node)
{
int length = sizeof (struct tree_exp);
#ifdef GATHER_STATISTICS
--- 2418,2424 ----
of varargs, which is expensive for RISC machines. */
tree
! build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
{
int length = sizeof (struct tree_exp);
#ifdef GATHER_STATISTICS
*************** build1 (enum tree_code code, tree type,
*** 2449,2455 ****
abort ();
#endif /* ENABLE_CHECKING */
! t = ggc_alloc_tree (length);
memset (t, 0, sizeof (struct tree_common));
--- 2451,2457 ----
abort ();
#endif /* ENABLE_CHECKING */
! t = ggc_alloc_zone_stat (length, tree_zone PASS_MEM_STAT);
memset (t, 0, sizeof (struct tree_common));
*************** build_nt (enum tree_code code, ...)
*** 2552,2562 ****
Other slots are initialized to 0 or null pointers. */
tree
! build_decl (enum tree_code code, tree name, tree type)
{
tree t;
! t = make_node (code);
/* if (type == error_mark_node)
type = integer_type_node; */
--- 2554,2564 ----
Other slots are initialized to 0 or null pointers. */
tree
! build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
{
tree t;
! t = make_node_stat (code PASS_MEM_STAT);
/* if (type == error_mark_node)
type = integer_type_node; */
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.458
diff -c -3 -p -r1.458 tree.h
*** tree.h 16 Jan 2004 07:20:29 -0000 1.458
--- tree.h 21 Jan 2004 18:27:08 -0000
*************** Software Foundation, 59 Temple Place - S
*** 25,30 ****
--- 25,31 ----
#include "machmode.h"
#include "version.h"
#include "input.h"
+ #include "statistics.h"
/* Codes of tree nodes */
*************** extern size_t tree_size (tree);
*** 2060,2070 ****
The TREE_CODE is the only argument. Contents are initialized
to zero except for a few of the common fields. */
! extern tree make_node (enum tree_code);
/* Make a copy of a node, with all the same contents. */
! extern tree copy_node (tree);
/* Make a copy of a chain of TREE_LIST nodes. */
--- 2061,2073 ----
The TREE_CODE is the only argument. Contents are initialized
to zero except for a few of the common fields. */
! extern tree make_node_stat (enum tree_code MEM_STAT_DECL);
! #define make_node(t) make_node_stat (t MEM_STAT_INFO)
/* Make a copy of a node, with all the same contents. */
! extern tree copy_node_stat (tree MEM_STAT_DECL);
! #define copy_node(t) copy_node_stat (t MEM_STAT_INFO)
/* Make a copy of a chain of TREE_LIST nodes. */
*************** extern tree copy_list (tree);
*** 2072,2078 ****
/* Make a TREE_VEC. */
! extern tree make_tree_vec (int);
/* Return the (unique) IDENTIFIER_NODE node for a given name.
The name is supplied as a char *. */
--- 2075,2082 ----
/* Make a TREE_VEC. */
! extern tree make_tree_vec_stat (int MEM_STAT_DECL);
! #define make_tree_vec(t) make_tree_vec_stat (t MEM_STAT_INFO)
/* Return the (unique) IDENTIFIER_NODE node for a given name.
The name is supplied as a char *. */
*************** extern tree build_constructor (tree, tre
*** 2112,2120 ****
extern tree build_real_from_int_cst (tree, tree);
extern tree build_complex (tree, tree, tree);
extern tree build_string (int, const char *);
! extern tree build1 (enum tree_code, tree, tree);
! extern tree build_tree_list (tree, tree);
! extern tree build_decl (enum tree_code, tree, tree);
extern tree build_block (tree, tree, tree, tree, tree);
extern tree build_expr_wfl (tree, const char *, int, int);
--- 2116,2127 ----
extern tree build_real_from_int_cst (tree, tree);
extern tree build_complex (tree, tree, tree);
extern tree build_string (int, const char *);
! extern tree build1_stat (enum tree_code, tree, tree MEM_STAT_DECL);
! #define build1(c,t,q) build1_stat (c,t,q MEM_STAT_INFO)
! extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
! #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
! extern tree build_decl_stat (enum tree_code, tree, tree MEM_STAT_DECL);
! #define build_decl(c,t,q) build_decl_stat (c,t,q MEM_STAT_INFO)
extern tree build_block (tree, tree, tree, tree, tree);
extern tree build_expr_wfl (tree, const char *, int, int);
*************** extern tree chainon (tree, tree);
*** 2468,2474 ****
/* Make a new TREE_LIST node from specified PURPOSE, VALUE and CHAIN. */
! extern tree tree_cons (tree, tree, tree);
/* Return the last tree node in a chain. */
--- 2475,2482 ----
/* Make a new TREE_LIST node from specified PURPOSE, VALUE and CHAIN. */
! extern tree tree_cons_stat (tree, tree, tree MEM_STAT_DECL);
! #define tree_cons(t,q,w) tree_cons_stat (t,q,w MEM_STAT_INFO)
/* Return the last tree node in a chain. */
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1229
diff -c -3 -p -r1.1229 Makefile.in
*** Makefile.in 20 Jan 2004 20:36:18 -0000 1.1229
--- Makefile.in 21 Jan 2004 18:55:46 -0000
*************** LANGHOOKS_DEF_H = langhooks-def.h $(HOOK
*** 655,664 ****
TARGET_DEF_H = target-def.h $(HOOKS_H)
MACHMODE_H = machmode.h mode-classes.def insn-modes.h
RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H)
! RTL_H = $(RTL_BASE_H) genrtl.h input.h
PARAMS_H = params.h params.def
TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \
! input.h
BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \
hard-reg-set.h cfghooks.h
COVERAGE_H = coverage.h gcov-io.h gcov-iov.h
--- 655,664 ----
TARGET_DEF_H = target-def.h $(HOOKS_H)
MACHMODE_H = machmode.h mode-classes.def insn-modes.h
RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H)
! RTL_H = $(RTL_BASE_H) genrtl.h input.h statistics.h
PARAMS_H = params.h params.def
TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \
! input.h statistics.h
BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \
hard-reg-set.h cfghooks.h
COVERAGE_H = coverage.h gcov-io.h gcov-iov.h
*************** bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM
*** 1731,1737 ****
global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
reload.h function.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h \
toplev.h $(TM_P_H)
! varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h $(GGC_H) errors.h
ra.o : ra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h \
$(RECOG_H) $(INTEGRATE_H) function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h \
$(BASIC_BLOCK_H) df.h $(EXPR_H) output.h toplev.h flags.h reload.h ra.h
--- 1731,1738 ----
global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
reload.h function.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h \
toplev.h $(TM_P_H)
! varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h $(GGC_H) errors.h \
! $(HASHTAB_H)
ra.o : ra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h \
$(RECOG_H) $(INTEGRATE_H) function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h \
$(BASIC_BLOCK_H) df.h $(EXPR_H) output.h toplev.h flags.h reload.h ra.h
Index: ggc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc-common.c,v
retrieving revision 1.78
diff -c -3 -p -r1.78 ggc-common.c
*** ggc-common.c 29 Oct 2003 22:13:59 -0000 1.78
--- ggc-common.c 21 Jan 2004 19:01:02 -0000
*************** ggc_mark_roots (void)
*** 129,150 ****
/* Allocate a block of memory, then clear it. */
void *
! ggc_alloc_cleared (size_t size)
{
! void *buf = ggc_alloc (size);
memset (buf, 0, size);
return buf;
}
/* Resize a block of memory, possibly re-allocating it. */
void *
! ggc_realloc (void *x, size_t size)
{
void *r;
size_t old_size;
if (x == NULL)
! return ggc_alloc (size);
old_size = ggc_get_size (x);
if (size <= old_size)
--- 129,150 ----
/* Allocate a block of memory, then clear it. */
void *
! ggc_alloc_cleared_stat (size_t size MEM_STAT_DECL)
{
! void *buf = ggc_alloc_stat (size PASS_MEM_STAT);
memset (buf, 0, size);
return buf;
}
/* Resize a block of memory, possibly re-allocating it. */
void *
! ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
{
void *r;
size_t old_size;
if (x == NULL)
! return ggc_alloc_stat (size PASS_MEM_STAT);
old_size = ggc_get_size (x);
if (size <= old_size)
*************** ggc_realloc (void *x, size_t size)
*** 165,171 ****
return x;
}
! r = ggc_alloc (size);
/* Since ggc_get_size returns the size of the pool, not the size of the
individually allocated object, we'd access parts of the old object
--- 165,171 ----
return x;
}
! r = ggc_alloc_stat (size PASS_MEM_STAT);
/* Since ggc_get_size returns the size of the pool, not the size of the
individually allocated object, we'd access parts of the old object
*************** init_ggc_heuristics (void)
*** 758,762 ****
--- 758,899 ----
#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
set_param_value ("ggc-min-expand", ggc_min_expand_heuristic());
set_param_value ("ggc-min-heapsize", ggc_min_heapsize_heuristic());
+ #endif
+ }
+
+ #ifdef GATHER_STATISTICS
+
+ /* Datastructure used to store per-call-site statistics. */
+ struct loc_descriptor
+ {
+ const char *file;
+ int line;
+ const char *function;
+ int times;
+ size_t allocated;
+ size_t overhead;
+ };
+
+ /* Hashtable used for statistics. */
+ static htab_t loc_hash;
+
+ /* Hash table helpers functions. */
+ static hashval_t
+ hash_descriptor (const void *p)
+ {
+ const struct loc_descriptor *d = p;
+
+ return htab_hash_pointer (d->function) | d->line;
+ }
+
+ static int
+ eq_descriptor (const void *p1, const void *p2)
+ {
+ const struct loc_descriptor *d = p1;
+ const struct loc_descriptor *d2 = p2;
+
+ return (d->file == d2->file && d->line == d2->line
+ && d->function == d2->function);
+ }
+
+ /* Return descriptor for given call site, create new one if needed. */
+ static struct loc_descriptor *
+ loc_descriptor (const char *name, int line, const char *function)
+ {
+ struct loc_descriptor loc;
+ struct loc_descriptor **slot;
+
+ loc.file = name;
+ loc.line = line;
+ loc.function = function;
+ if (!loc_hash)
+ loc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
+
+ slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, 1);
+ if (*slot)
+ return *slot;
+ *slot = xcalloc (sizeof (**slot), 1);
+ (*slot)->file = name;
+ (*slot)->line = line;
+ (*slot)->function = function;
+ return *slot;
+ }
+
+ /* Record ALLOCATED and OVERHEAD bytes to descritor NAME:LINE (FUNCTION). */
+ void ggc_record_overhead (size_t allocated, size_t overhead,
+ const char *name, int line, const char *function)
+ {
+ struct loc_descriptor *loc = loc_descriptor (name, line, function);
+
+ loc->times++;
+ loc->allocated+=allocated;
+ loc->overhead+=overhead;
+ }
+
+ /* Helper for qsort; sort descriptors by amount of memory consumed. */
+ static int
+ cmp_statistic (const void *loc1, const void *loc2)
+ {
+ struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1;
+ struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2;
+ return (l1->allocated + l1->overhead) - (l2->allocated + l2->overhead);
+ }
+
+ /* Collect array of the descriptors from hashtable. */
+ struct loc_descriptor **loc_array;
+ static int
+ add_statistics (void **slot, void *b)
+ {
+ int *n = (int *)b;
+ loc_array[*n] = (struct loc_descriptor *) *slot;
+ (*n)++;
+ return 1;
+ }
+
+ /* Dump per-site memory statistics. */
+ #endif
+ void dump_ggc_loc_statistics (void)
+ {
+ #ifdef GATHER_STATISTICS
+ int nentries = 0;
+ char s[4096];
+ size_t count, size, overhead;
+ int i;
+
+ loc_array = xcalloc (sizeof (*loc_array), loc_hash->n_elements);
+ fprintf (stderr, "-------------------------------------------------------\n");
+ fprintf (stderr, "\n%-60s %10s %10s %10s\n",
+ "source location", "Times", "Allocated", "Overhead");
+ fprintf (stderr, "-------------------------------------------------------\n");
+ count = 0;
+ size = 0;
+ overhead = 0;
+ htab_traverse (loc_hash, add_statistics, &nentries);
+ qsort (loc_array, nentries, sizeof (*loc_array), cmp_statistic);
+ for (i = 0; i < nentries; i++)
+ {
+ struct loc_descriptor *d = loc_array[i];
+ size += d->allocated;
+ count += d->times;
+ overhead += d->overhead;
+ }
+ for (i = 0; i < nentries; i++)
+ {
+ struct loc_descriptor *d = loc_array[i];
+ if (d->allocated)
+ {
+ const char *s1 = d->file;
+ const char *s2;
+ while ((s2 = strstr (s1, "gcc/")))
+ s1 = s2 + 4;
+ sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
+ fprintf (stderr, "%-60s %10i %10li %10li:%.3f%%\n", s,
+ d->times, (long)d->allocated, (long)d->overhead,
+ (d->allocated + d->overhead) *100.0 / (size + overhead));
+ }
+ }
+ fprintf (stderr, "%-60s %10ld %10ld %10ld\n",
+ "Total", (long)count, (long)size, (long)overhead);
+ fprintf (stderr, "-------------------------------------------------------\n");
#endif
}
/* Memory statistics helpers.
Copyright (C) 2004
Free Software Foundation, Inc.
Contributed by Cygnus Solutions.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#ifndef GCC_STATISTICS
#define GCC_STATISTICS
#ifdef GATHER_STATISTICS
#define MEM_STAT_DECL , const char *_loc_name ATTRIBUTE_UNUSED, int _loc_line ATTRIBUTE_UNUSED, const char *_loc_function ATTRIBUTE_UNUSED
#define PASS_MEM_STAT , _loc_name, _loc_line, _loc_function
#define MEM_STAT_INFO , __FILE__, __LINE__, __FUNCTION__
#else
#define MEM_STAT_DECL
#define PASS_MEM_STAT
#define MEM_STAT_INFO
#endif
#endif
More information about the Gcc-patches
mailing list