This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: Don't clear memory returned by ggc_alloc
- To: gcc-patches at gcc dot gnu dot org
- Subject: Patch: Don't clear memory returned by ggc_alloc
- From: Zack Weinberg <zack at wolery dot cumb dot org>
- Date: Wed, 7 Jun 2000 16:25:25 -0700
If you profile cc1 on a file that doesn't hit any of the nonlinear
bottlenecks, you'll see us spending from 5-10% of runtime in
memset(). We call it millions of times, mostly from ggc_alloc_obj.
But the memory blocks returned by ggc_alloc_obj are almost always
going to be initialized thoroughly - by gen_rtx_fmt_xyz, or build, or
whatever - so clearing the memory is a pure waste of time.
This patch causes ggc_alloc_obj to always return uninitialized
memory. I then had to go through, find all the places where we didn't
initialize every word of that memory, and fix them. There were only a
few. ggc_alloc_obj is renamed to ggc_alloc, which was the name of an
existing wrapper macro that didn't clear returned memory.
There are still improvements in this area - particularly in tree.c
which now does a good bit of clearing itself. But we allocate lots
more RTL than trees. The way forward for tree.c, I think, is to make
a gengentree and convert all uses of build(FOO_EXPR, ...) to
build_FOO_EXPR(...). You could probably do the same with most uses of
make_node.
The patch has survived a bootstrap and testsuite run with every last
--enable-checking option active - this takes 12 hours! and I thought
my box was overspecified... Compiling insn-recog.c in stage2 alone
chewed up more than an hour. There are no regressions in the gcc,
g77, objc, libio, or libstdc++ test suites. There are several
regressions in the g++ test suite; I believe all of them are unrelated
to my patch. I'll be trying Geoff's VOID_TYPE_P patch overnight.
FAIL: g++.brendan/scope1.C caused compiler crash
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 18)
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 20)
FAIL: g++.jason/local.C caused compiler crash
FAIL: g++.jason/report.C caused compiler crash
FAIL: g++.law/visibility13.C caused compiler crash
FAIL: g++.law/visibility3.C caused compiler crash
FAIL: g++.law/visibility8.C caused compiler crash
FAIL: g++.martin/sts_partial.C caused compiler crash
FAIL: g++.mike/p11110.C caused compiler crash
FAIL: g++.pt/call2.C caused compiler crash
FAIL: g++.pt/crash36.C caused compiler crash
FAIL: g++.pt/memtemp96.C (test for excess errors)
FAIL: g++.pt/nttp1.C caused compiler crash
FAIL: g++.pt/nttp2.C caused compiler crash
FAIL: g++.pt/t24.C caused compiler crash
FAIL: g++.pt/ttp10.C caused compiler crash
FAIL: g++.robertl/eb22.C caused compiler crash
zw
* ggc-none.c (ggc_alloc_obj): Just call xmalloc.
* ggc-page.c (ggc_alloc_obj): Do not clear returned memory.
* ggc-simple.c (ggc_alloc_obj): Do not clear returned memory.
* ggc.h (ggc_alloc_obj): Rename to ggc_alloc.
(ggc_alloc_rtx, ggc_alloc_rtvec, ggc_alloc_tree): Update.
* ggc-common.c (ggc_alloc_string): Update.
* stmt.c (expand_fixup): Update.
* c-typeck.c (add_pending_init): Update.
* emit-rtl.c (init_emit_once): Clear CONST_DOUBLE_CHAIN (tem).
* gengenrtl.c (gendef): Clear initial word in both allocation
schemes. Clear '0' slots.
(all): Replace printf with puts where possible; remove
unnecessary newlines.
* rtl.c (rtvec_alloc): Clear vector in both allocation schemes.
(rtx_alloc): Clear first word in both allocation schemes.
Eliminate dirty obstack tricks.
* tree.c (make_node, make_tree_vec): Clear node in both
allocation schemes.
(tree_cons, build1): Clear common area in both allocation schemes.
(tree_class_check_failed): Make second arg an int.
* tree.h (tree_class_check_failed): Update prototype.
* varasm.c (immed_double_const): Set mem-slot to const0_rtx at
creation time.
(immed_real_const_1): If we aren't inside a function, set
CONST_DOUBLE_CHAIN(r) to NULL_RTX.
cp:
* call.c (add_candidate): Initialize all slots of the new
struct z_candidate.
* decl.c (lookup_label): Initialize all slots of the new
struct named_label_list.
* lex.c (retrofit_lang_decl): Clear the new structure.
===================================================================
Index: ggc-none.c
--- ggc-none.c 1999/10/13 17:09:18 1.7
+++ ggc-none.c 2000/06/07 22:36:02
@@ -36,12 +36,8 @@
int ggc_p = 0;
void *
-ggc_alloc_obj (size, zero)
+ggc_alloc (size)
size_t size;
- int zero;
{
- void *p = xmalloc (size);
- if (zero)
- memset (p, 0, size);
- return p;
+ return xmalloc (size);
}
===================================================================
Index: ggc-page.c
--- ggc-page.c 2000/04/28 00:59:39 1.26
+++ ggc-page.c 2000/06/07 22:36:02
@@ -611,9 +611,8 @@ static unsigned char const size_lookup[2
memory is zeroed; otherwise, its contents are undefined. */
void *
-ggc_alloc_obj (size, zero)
+ggc_alloc (size)
size_t size;
- int zero;
{
unsigned order, word, bit, object_offset;
struct page_entry *entry;
@@ -703,13 +702,10 @@ ggc_alloc_obj (size, zero)
result = entry->page + object_offset;
#ifdef GGC_POISON
- /* `Poison' the entire allocated object before zeroing the requested area,
- so that bytes beyond the end, if any, will not necessarily be zero. */
+ /* `Poison' the entire allocated object, including any padding at
+ the end. */
memset (result, 0xaf, 1 << order);
#endif
-
- if (zero)
- memset (result, 0, size);
/* Keep track of how many bytes are being allocated. This
information is used in deciding when to collect. */
===================================================================
Index: ggc-simple.c
--- ggc-simple.c 2000/05/12 17:07:02 1.33
+++ ggc-simple.c 2000/06/07 22:36:02
@@ -182,9 +182,8 @@ tree_lookup (v)
/* Alloc SIZE bytes of GC'able memory. If ZERO, clear the memory. */
void *
-ggc_alloc_obj (size, zero)
+ggc_alloc (size)
size_t size;
- int zero;
{
struct ggc_mem *x;
@@ -195,11 +194,8 @@ ggc_alloc_obj (size, zero)
x->context = G.context;
x->size = size;
- if (zero)
- memset (&x->u, 0, size);
#ifdef GGC_POISON
- else
- memset (&x->u, 0xaf, size);
+ memset (&x->u, 0xaf, size);
#endif
tree_insert (x);
===================================================================
Index: ggc.h
--- ggc.h 2000/04/07 09:24:06 1.27
+++ ggc.h 2000/06/07 22:36:02
@@ -128,20 +128,17 @@ extern void ggc_pop_context PARAMS ((voi
/* Allocation. */
/* The internal primitive. */
-void *ggc_alloc_obj PARAMS ((size_t, int));
+void *ggc_alloc PARAMS ((size_t));
-#define ggc_alloc_rtx(NSLOTS) \
- ((struct rtx_def *) ggc_alloc_obj (sizeof (struct rtx_def) \
- + ((NSLOTS) - 1) * sizeof (rtunion), 1))
+#define ggc_alloc_rtx(NSLOTS) \
+ ((struct rtx_def *) ggc_alloc (sizeof (struct rtx_def) \
+ + ((NSLOTS) - 1) * sizeof (rtunion)))
#define ggc_alloc_rtvec(NELT) \
- ((struct rtvec_def *) ggc_alloc_obj (sizeof (struct rtvec_def) \
- + ((NELT) - 1) * sizeof (rtx), 1))
+ ((struct rtvec_def *) ggc_alloc (sizeof (struct rtvec_def) \
+ + ((NELT) - 1) * sizeof (rtx)))
-#define ggc_alloc_tree(LENGTH) \
- ((union tree_node *) ggc_alloc_obj ((LENGTH), 1))
-
-#define ggc_alloc(SIZE) ggc_alloc_obj((SIZE), 0)
+#define ggc_alloc_tree(LENGTH) ((union tree_node *) ggc_alloc (LENGTH))
char *ggc_alloc_string PARAMS ((const char *contents, int length));
===================================================================
Index: ggc-common.c
--- ggc-common.c 2000/05/27 15:21:15 1.28
+++ ggc-common.c 2000/06/07 22:36:02
@@ -580,7 +580,7 @@ ggc_alloc_string (contents, length)
length = strlen (contents);
}
- string = (char *) ggc_alloc_obj (length + 1, 0);
+ string = (char *) ggc_alloc (length + 1);
if (contents != NULL)
memcpy (string, contents, length);
string[length] = 0;
===================================================================
Index: c-typeck.c
--- c-typeck.c 2000/06/06 06:55:35 1.70
+++ c-typeck.c 2000/06/07 22:36:01
@@ -5595,7 +5595,7 @@ add_pending_init (purpose, value)
}
}
- r = (struct init_node *) ggc_alloc_obj (sizeof (struct init_node), 0);
+ r = (struct init_node *) ggc_alloc (sizeof (struct init_node));
r->purpose = purpose;
r->value = value;
===================================================================
Index: emit-rtl.c
--- emit-rtl.c 2000/05/26 01:49:38 1.134
+++ emit-rtl.c 2000/06/07 22:36:02
@@ -4125,6 +4125,7 @@ init_emit_once (line_numbers)
bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (tem), sizeof u);
CONST_DOUBLE_MEM (tem) = cc0_rtx;
+ CONST_DOUBLE_CHAIN (tem) = NULL_RTX;
PUT_MODE (tem, mode);
const_tiny_rtx[i][(int) mode] = tem;
===================================================================
Index: gengenrtl.c
--- gengenrtl.c 2000/04/21 19:09:18 1.34
+++ gengenrtl.c 2000/06/07 22:36:02
@@ -272,7 +272,7 @@ genmacro (idx)
if (*p != '0')
printf (", (ARG%d)", i++);
- printf (")\n");
+ puts (")");
}
/* Generate the code for the function to generate RTL whose
@@ -293,30 +293,31 @@ gendef (format)
if (*p != '0')
printf (", arg%d", i++);
- printf (")\n RTX_CODE code;\n enum machine_mode mode;\n");
+ puts (")\n RTX_CODE code;\n enum machine_mode mode;");
for (p = format, i = 0; *p != 0; p++)
if (*p != '0')
printf (" %sarg%d;\n", type_from_format (*p), i++);
/* Now write out the body of the function itself, which allocates
the memory and initializes it. */
- printf ("{\n");
- printf (" rtx rt;\n");
- printf (" if (ggc_p)\n");
- printf (" rt = ggc_alloc_rtx (%d);\n",
- (int) strlen (format));
- printf (" else\n");
- printf (" rt = obstack_alloc_rtx (sizeof (struct rtx_def) + %d * sizeof (rtunion));\n",
- (int) strlen (format) - 1);
+ puts ("{");
+ puts (" rtx rt;");
+ puts (" if (ggc_p)");
+ printf (" rt = ggc_alloc_rtx (%d);\n", (int) strlen (format));
+ puts (" else");
+ printf (" rt = obstack_alloc_rtx (%d);\n", (int) strlen (format));
+
+ puts (" memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));\n");
+ puts (" PUT_CODE (rt, code);");
+ puts (" PUT_MODE (rt, mode);");
- printf (" PUT_CODE (rt, code);\n");
- printf (" PUT_MODE (rt, mode);\n");
-
for (p = format, i = j = 0; *p ; ++p, ++i)
if (*p != '0')
printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
+ else
+ printf (" X0EXP (rt, %d) = NULL_RTX;\n", i);
- printf ("\n return rt;\n}\n\n");
+ puts ("\n return rt;\n}\n");
}
/* Generate the documentation header for files we write. */
@@ -324,8 +325,7 @@ gendef (format)
static void
genlegend ()
{
- printf ("/* Generated automatically by the program `gengenrtl'\n");
- printf (" from the RTL description file `rtl.def' */\n\n");
+ puts ("/* Generated automatically by gengenrtl from rtl.def. */\n");
}
/* Generate the text of the header file we make, genrtl.h. */
@@ -339,7 +339,7 @@ genheader ()
for (fmt = formats; *fmt; ++fmt)
gendecl (*fmt);
- printf ("\n");
+ putchar ('\n');
for (i = 0; i < NUM_RTX_CODE; i++)
if (! special_format (defs[i].format))
@@ -353,19 +353,16 @@ gencode ()
{
const char **fmt;
- puts ("#include \"config.h\"\n");
- puts ("#include \"system.h\"\n");
- puts ("#include \"obstack.h\"\n");
- puts ("#include \"rtl.h\"\n");
- puts ("#include \"ggc.h\"\n\n");
- puts ("extern struct obstack *rtl_obstack;\n\n");
- puts ("static rtx obstack_alloc_rtx PARAMS ((int length));\n");
- puts ("static rtx\n");
- puts ("obstack_alloc_rtx (length)\n");
- puts (" register int length;\n{\n");
- puts (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n");
- puts (" memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n");
- puts (" return rt;\n}\n\n");
+ puts ("#include \"config.h\"");
+ puts ("#include \"system.h\"");
+ puts ("#include \"obstack.h\"");
+ puts ("#include \"rtl.h\"");
+ puts ("#include \"ggc.h\"\n");
+ puts ("extern struct obstack *rtl_obstack;\n");
+ puts ("#define obstack_alloc_rtx(n) \\");
+ puts (" ((rtx) obstack_alloc (rtl_obstack, \\");
+ puts (" sizeof (struct rtx_def) \\");
+ puts (" + ((n) - 2) * sizeof (rtunion)))\n");
for (fmt = formats; *fmt != 0; fmt++)
gendef (*fmt);
===================================================================
Index: rtl.c
--- rtl.c 2000/04/21 19:32:09 1.69
+++ rtl.c 2000/06/07 22:36:02
@@ -275,21 +275,18 @@ rtvec_alloc (n)
int n;
{
rtvec rt;
-
+ int i;
+
if (ggc_p)
rt = ggc_alloc_rtvec (n);
else
- {
- int i;
-
- rt = (rtvec) obstack_alloc (rtl_obstack,
- sizeof (struct rtvec_def)
- + (( n - 1) * sizeof (rtx)));
-
- /* clear out the vector */
- for (i = 0; i < n; i++)
- rt->elem[i] = 0;
- }
+ rt = (rtvec) obstack_alloc (rtl_obstack,
+ sizeof (struct rtvec_def)
+ + ((n - 1) * sizeof (rtx)));
+
+ /* clear out the vector */
+ for (i = 0; i < n; i++)
+ rt->elem[i] = 0;
PUT_NUM_ELEM (rt, n);
return rt;
@@ -303,39 +300,20 @@ rtx_alloc (code)
RTX_CODE code;
{
rtx rt;
+ int n = GET_RTX_LENGTH (code);
if (ggc_p)
- rt = ggc_alloc_rtx (GET_RTX_LENGTH (code));
+ rt = ggc_alloc_rtx (n);
else
- {
- register struct obstack *ob = rtl_obstack;
- register int nelts = GET_RTX_LENGTH (code);
- register int length = sizeof (struct rtx_def)
- + (nelts - 1) * sizeof (rtunion);
-
- /* This function is called more than any other in GCC, so we
- manipulate the obstack directly.
-
- Even though rtx objects are word aligned, we may be sharing
- an obstack with tree nodes, which may have to be double-word
- aligned. So align our length to the alignment mask in the
- obstack. */
-
- length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
-
- if (ob->chunk_limit - ob->next_free < length)
- _obstack_newchunk (ob, length);
- rt = (rtx)ob->object_base;
- ob->next_free += length;
- ob->object_base = ob->next_free;
-
- /* 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 portable anyway; this is. */
-
- memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
- }
+ rt = (rtx) obstack_alloc (rtl_obstack,
+ sizeof (struct rtx_def)
+ + ((n - 1) * sizeof (rtunion)));
+
+ /* 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
+ portable anyway; this is. */
+ memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
PUT_CODE (rt, code);
return rt;
}
===================================================================
Index: stmt.c
--- stmt.c 2000/06/06 03:37:50 1.151
+++ stmt.c 2000/06/07 22:36:04
@@ -1011,7 +1011,7 @@ expand_fixup (tree_label, rtl_label, las
{
/* Ok, a fixup is needed. Add a fixup to the list of such. */
struct goto_fixup *fixup
- = (struct goto_fixup *) ggc_alloc_obj (sizeof (struct goto_fixup), 0);
+ = (struct goto_fixup *) ggc_alloc (sizeof (struct goto_fixup));
/* In case an old stack level is restored, make sure that comes
after any pending stack adjust. */
/* ?? If the fixup isn't to come at the present position,
===================================================================
Index: tree.c
--- tree.c 2000/05/31 18:36:05 1.147
+++ tree.c 2000/06/07 23:13:43
@@ -1041,10 +1041,9 @@ make_node (code)
if (ggc_p)
t = ggc_alloc_tree (length);
else
- {
- t = (tree) obstack_alloc (obstack, length);
- memset ((PTR) t, 0, length);
- }
+ t = (tree) obstack_alloc (obstack, length);
+
+ memset ((PTR) t, 0, length);
#ifdef GATHER_STATISTICS
tree_node_counts[(int)kind]++;
@@ -1604,11 +1603,9 @@ make_tree_vec (len)
if (ggc_p)
t = ggc_alloc_tree (length);
else
- {
- t = (tree) obstack_alloc (obstack, length);
- bzero ((PTR) t, length);
- }
+ t = (tree) obstack_alloc (obstack, length);
+ memset ((PTR) t, 0, length);
TREE_SET_CODE (t, TREE_VEC);
TREE_VEC_LENGTH (t) = len;
TREE_SET_PERMANENT (t);
@@ -2164,10 +2161,9 @@ tree_cons (purpose, value, chain)
if (ggc_p)
node = ggc_alloc_tree (sizeof (struct tree_list));
else
- {
- node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
- memset (node, 0, sizeof (struct tree_common));
- }
+ node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
+
+ memset (node, 0, sizeof (struct tree_common));
#ifdef GATHER_STATISTICS
tree_node_counts[(int) x_kind]++;
@@ -3384,10 +3380,9 @@ build1 (code, type, node)
if (ggc_p)
t = ggc_alloc_tree (length);
else
- {
- t = (tree) obstack_alloc (obstack, length);
- memset ((PTR) t, 0, length);
- }
+ t = (tree) obstack_alloc (obstack, length);
+
+ memset ((PTR) t, 0, sizeof (struct tree_common));
#ifdef GATHER_STATISTICS
tree_node_counts[(int)kind]++;
@@ -5597,7 +5592,7 @@ tree_check_failed (node, code, file, lin
void
tree_class_check_failed (node, cl, file, line, function)
const tree node;
- char cl;
+ int cl;
const char *file;
int line;
const char *function;
===================================================================
Index: tree.h
--- tree.h 2000/06/05 13:16:13 1.177
+++ tree.h 2000/06/07 22:36:05
@@ -309,10 +309,10 @@ struct tree_common
__t; })
extern void tree_check_failed PARAMS ((const tree, enum tree_code,
- const char *, int, const char *))
+ const char *, int, const char *))
ATTRIBUTE_NORETURN;
-extern void tree_class_check_failed PARAMS ((const tree, char,
- const char *, int, const char *))
+extern void tree_class_check_failed PARAMS ((const tree, int,
+ const char *, int, const char *))
ATTRIBUTE_NORETURN;
#else /* not ENABLE_TREE_CHECKING, or not gcc */
===================================================================
Index: varasm.c
--- varasm.c 2000/06/01 16:18:18 1.123
+++ varasm.c 2000/06/07 22:36:06
@@ -2121,7 +2121,7 @@ immed_double_const (i0, i1, mode)
push_obstacks_nochange ();
rtl_in_saveable_obstack ();
- r = gen_rtx_CONST_DOUBLE (mode, NULL_RTX, i0, i1);
+ r = gen_rtx_CONST_DOUBLE (mode, const0_rtx, i0, i1);
pop_obstacks ();
/* Don't touch const_double_chain if not inside any function. */
@@ -2131,11 +2131,6 @@ immed_double_const (i0, i1, mode)
const_double_chain = r;
}
- /* Store const0_rtx in mem-slot since this CONST_DOUBLE is on the chain.
- Actual use of mem-slot is only through force_const_mem. */
-
- CONST_DOUBLE_MEM (r) = const0_rtx;
-
return r;
}
@@ -2201,12 +2196,15 @@ immed_real_const_1 (d, mode)
PUT_MODE (r, mode);
bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (r), sizeof u);
- /* Don't touch const_double_chain if not inside any function. */
+ /* If we aren't inside a function, don't put r on the
+ const_double_chain. */
if (current_function_decl != 0)
{
CONST_DOUBLE_CHAIN (r) = const_double_chain;
const_double_chain = r;
}
+ else
+ CONST_DOUBLE_CHAIN (r) = NULL_RTX;
/* Store const0_rtx in CONST_DOUBLE_MEM since this CONST_DOUBLE is on the
chain, but has not been allocated memory. Actual use of CONST_DOUBLE_MEM
===================================================================
Index: cp/call.c
--- cp/call.c 2000/05/31 19:27:11 1.220
+++ cp/call.c 2000/06/07 22:36:08
@@ -1250,12 +1250,16 @@ add_candidate (candidates, fn, convs, vi
int viable;
{
struct z_candidate *cand
- = (struct z_candidate *) ggc_alloc_obj (sizeof (struct z_candidate), 1);
+ = (struct z_candidate *) ggc_alloc (sizeof (struct z_candidate));
- cand->fn = fn;
- cand->convs = convs;
- cand->viable = viable;
- cand->next = candidates;
+ cand->fn = fn;
+ cand->convs = convs;
+ cand->second_conv = NULL_TREE;
+ cand->viable = viable;
+ cand->basetype_path = NULL_TREE;
+ cand->template = NULL_TREE;
+ cand->warnings = NULL_TREE;
+ cand->next = candidates;
return cand;
}
===================================================================
Index: cp/decl.c
--- cp/decl.c 2000/06/07 07:59:00 1.628
+++ cp/decl.c 2000/06/07 23:21:06
@@ -4832,9 +4832,13 @@ lookup_label (id)
We do this before calling make_label_decl so that we get the
IDENTIFIER_LABEL_VALUE before the new label is declared. */
ent = ((struct named_label_list *)
- ggc_alloc_obj (sizeof (struct named_label_list), 1));
- ent->old_value = IDENTIFIER_LABEL_VALUE (id);
- ent->next = named_labels;
+ ggc_alloc (sizeof (struct named_label_list)));
+ ent->binding_level = NULL;
+ ent->names_in_scope = NULL_TREE;
+ ent->old_value = IDENTIFIER_LABEL_VALUE (id);
+ ent->bad_decls = NULL_TREE;
+ ent->eh_region = 0;
+ ent->next = named_labels;
named_labels = ent;
/* We need a new label. */
===================================================================
Index: cp/lex.c
--- cp/lex.c 2000/06/06 20:11:40 1.201
+++ cp/lex.c 2000/06/07 22:36:12
@@ -4776,7 +4776,8 @@ retrofit_lang_decl (t)
else
size = sizeof (struct lang_decl_flags);
- ld = (struct lang_decl *) ggc_alloc_obj (size, 1);
+ ld = (struct lang_decl *) ggc_alloc (size);
+ memset (ld, 0, size);
DECL_LANG_SPECIFIC (t) = ld;
if (current_lang_name == lang_name_cplusplus)