Commit a3770a81 by Richard Henderson Committed by Mark Mitchell

Makefile.in (ggc-simple.o): Depend on varray.h.

	* Makefile.in (ggc-simple.o): Depend on varray.h.
	(rtl.o): Depend on ggc.h.
	(genattrtab.o): Depend on ggc.h.
	(print-tree.o): Likewise.
	(fold-const.o): Likewise.
	* emit-rtl.c (sequence_element_free_list): Remove, and all references.
	(make_insn_raw): Don't cache insns when GC'ing.
	(emit_insn_before): Likewise.
	(emit_insn_after): Likewise.
	(emit_insn): Likewise.
	(start_sequence): Use xmalloc to allocate the sequence_stack.
	(end_sequence): Add free to free it.
	(gen_sequence): Don't cache insns when GC'ing.
	(clear_emit_caches): Don't use sequence_element_free_list.
	(init_emit): Use xcalloc, not xmalloc+bzero.
	* fold-const.c (size_int_wide): Kill the cache, when GC'ing.
	* function.c (pop_function_context_from): Use free to free the
	fixup_var_refs_queue.
	(put_reg_into_stack): Allocate it with xmalloc.
	* genattrtab.c: Include ggc.h.
	(operate_exp): Don't use obstack_free when GC'ing.
	(simplify_cond): Likewise.
	(simplify_text_exp): Likewise.
	(optimize_attrs): Likewise.
	* gengentrtl.c (gendef): Use ggc_alloc_rtx to allocate RTL, when
	GC'ing.
	(gencode): Generate a #include for ggc.h.
	* ggc-callbacks.c (ggc_p): Define it to zero.
	* ggc-none.c (ggc_p): Likewise.
	* ggc-simple.c: Include varray.h.
	(ggc_mark_tree_varray): New function.
	(ggc_add_tree_varray_root): Likewise.
	(ggc_mark_tree_varray_ptr): Likewise.
	* ggc.h (ggc_p): Declare.
	(varray_head_tag): Likewise.
	(ggc_add_tree_varray_root): Declare.
	* print-tree.c (print_node): Don't check for TREE_PERMANENT
	inconsistencies when GC'ing.
	* rtl.c: Include ggc.h.
	(rtvec_alloc): Use ggc_alloc_rtvec when GC'ing.
	(rtx_alloc): Use ggc_alloc_rtx when GC'ing.
	(rtx_free): Don't call obstack_free when GC'ing.
	* toplev.c (rest_of_compilation): Call ggc_collect after every
	pass, if GC'ing.
	* tree.c (push_obstacks): Do nothing, if GC'ing.
	(pop_obstacks_nochange): Likewise.
	(pop_obstacks): Likewise.
	(make_node): Use ggc_alloc_tree when GC'ing.
	(copy_node): Likewise.
	(get_identifier): Use ggc_alloc_string when GC'ing.
	(build_string): Likewise.
	(make_tree_vec): Use ggc_alloc_tree when GC'ing.
	(tree_cons): Likewise.
	(build1): Likewise.
	(type_hash_canon): Don't call obstack_free when GC'ing.

Co-Authored-By: Bernd Schmidt <bernds@cygnus.co.uk>
Co-Authored-By: Mark Mitchell <mark@codesourcery.com>

From-SVN: r29125
parent 616aedda
Sun Sep 5 00:35:17 1999 Richard Henderson <rth@cygnus.com>
Bernd Schmidt <bernds@cygnus.co.uk>
Mark Mitchell <mark@codesourcery.com>
* Makefile.in (ggc-simple.o): Depend on varray.h.
(rtl.o): Depend on ggc.h.
(genattrtab.o): Depend on ggc.h.
(print-tree.o): Likewise.
(fold-const.o): Likewise.
* emit-rtl.c (sequence_element_free_list): Remove, and all references.
(make_insn_raw): Don't cache insns when GC'ing.
(emit_insn_before): Likewise.
(emit_insn_after): Likewise.
(emit_insn): Likewise.
(start_sequence): Use xmalloc to allocate the sequence_stack.
(end_sequence): Add free to free it.
(gen_sequence): Don't cache insns when GC'ing.
(clear_emit_caches): Don't use sequence_element_free_list.
(init_emit): Use xcalloc, not xmalloc+bzero.
* fold-const.c (size_int_wide): Kill the cache, when GC'ing.
* function.c (pop_function_context_from): Use free to free the
fixup_var_refs_queue.
(put_reg_into_stack): Allocate it with xmalloc.
* genattrtab.c: Include ggc.h.
(operate_exp): Don't use obstack_free when GC'ing.
(simplify_cond): Likewise.
(simplify_text_exp): Likewise.
(optimize_attrs): Likewise.
* gengentrtl.c (gendef): Use ggc_alloc_rtx to allocate RTL, when
GC'ing.
(gencode): Generate a #include for ggc.h.
* ggc-callbacks.c (ggc_p): Define it to zero.
* ggc-none.c (ggc_p): Likewise.
* ggc-simple.c: Include varray.h.
(ggc_mark_tree_varray): New function.
(ggc_add_tree_varray_root): Likewise.
(ggc_mark_tree_varray_ptr): Likewise.
* ggc.h (ggc_p): Declare.
(varray_head_tag): Likewise.
(ggc_add_tree_varray_root): Declare.
* print-tree.c (print_node): Don't check for TREE_PERMANENT
inconsistencies when GC'ing.
* rtl.c: Include ggc.h.
(rtvec_alloc): Use ggc_alloc_rtvec when GC'ing.
(rtx_alloc): Use ggc_alloc_rtx when GC'ing.
(rtx_free): Don't call obstack_free when GC'ing.
* toplev.c (rest_of_compilation): Call ggc_collect after every
pass, if GC'ing.
* tree.c (push_obstacks): Do nothing, if GC'ing.
(pop_obstacks_nochange): Likewise.
(pop_obstacks): Likewise.
(make_node): Use ggc_alloc_tree when GC'ing.
(copy_node): Likewise.
(get_identifier): Use ggc_alloc_string when GC'ing.
(build_string): Likewise.
(make_tree_vec): Use ggc_alloc_tree when GC'ing.
(tree_cons): Likewise.
(build1): Likewise.
(type_hash_canon): Don't call obstack_free when GC'ing.
Sat Sep 4 21:52:32 1999 Richard Henderson <rth@cygnus.com>
* haifa-sched.c (schedule_block): Use next_nonnote_insn instead
......
......@@ -1432,7 +1432,8 @@ dumpvers: dumpvers.c
version.o: version.c
ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) flags.h ggc.h
ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_BASE_H) $(TREE_H) flags.h \
ggc.h varray.h
ggc-none.o: ggc-none.c $(CONFIG_H) $(RTL_BASE_H) ggc.h
......@@ -1452,11 +1453,11 @@ convert.o: convert.c $(CONFIG_H) $(TREE_H) flags.h convert.h toplev.h
tree.o : tree.c $(CONFIG_H) system.h $(TREE_H) flags.h function.h toplev.h \
ggc.h
print-tree.o : print-tree.c $(CONFIG_H) system.h $(TREE_H)
print-tree.o : print-tree.c $(CONFIG_H) system.h $(TREE_H) ggc.h
stor-layout.o : stor-layout.c $(CONFIG_H) system.h $(TREE_H) flags.h \
function.h $(EXPR_H) $(RTL_H) toplev.h ggc.h
fold-const.o : fold-const.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h \
$(RTL_H)
$(RTL_H) ggc.h
toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) function.h \
flags.h input.h insn-attr.h xcoffout.h defaults.h output.h \
insn-codes.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h dwarfout.h \
......@@ -1466,7 +1467,7 @@ toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) function.h \
-DTARGET_NAME=\"$(target_alias)\" \
-c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h ggc.h
print-rtl.o : print-rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h basic-block.h
rtlanal.o : rtlanal.c $(CONFIG_H) system.h $(RTL_H)
......@@ -1845,7 +1846,7 @@ genattrtab : genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_RTLANA
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_RTLANAL) $(HOST_LIBS)
genattrtab.o : genattrtab.c $(RTL_H) $(build_xm_file) system.h insn-config.h errors.h
genattrtab.o : genattrtab.c $(RTL_H) $(build_xm_file) system.h insn-config.h errors.h ggc.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c
genoutput : genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
......
......@@ -158,21 +158,18 @@ struct rtx_def const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
/* start_sequence and gen_sequence can make a lot of rtx expressions which are
shortly thrown away. We use two mechanisms to prevent this waste:
First, we keep a list of the expressions used to represent the sequence
stack in sequence_element_free_list.
Second, for sizes up to 5 elements, we keep a SEQUENCE and its associated
rtvec for use by gen_sequence. One entry for each size is sufficient
because most cases are calls to gen_sequence followed by immediately
emitting the SEQUENCE. Reuse is safe since emitting a sequence is
destructive on the insn in it anyway and hence can't be redone.
For sizes up to 5 elements, we keep a SEQUENCE and its associated
rtvec for use by gen_sequence. One entry for each size is
sufficient because most cases are calls to gen_sequence followed by
immediately emitting the SEQUENCE. Reuse is safe since emitting a
sequence is destructive on the insn in it anyway and hence can't be
redone.
We do not bother to save this cached data over nested function calls.
Instead, we just reinitialize them. */
#define SEQUENCE_RESULT_SIZE 5
static struct sequence_stack *sequence_element_free_list;
static rtx sequence_result[SEQUENCE_RESULT_SIZE];
/* During RTL generation, we also keep a list of free INSN rtl codes. */
......@@ -2256,7 +2253,7 @@ make_insn_raw (pattern)
register rtx insn;
/* If in RTL generation phase, see if FREE_INSN can be used. */
if (free_insn != 0 && rtx_equal_function_value_matters)
if (!ggc_p && free_insn != 0 && rtx_equal_function_value_matters)
{
insn = free_insn;
free_insn = NEXT_INSN (free_insn);
......@@ -2600,7 +2597,7 @@ emit_insn_before (pattern, before)
insn = XVECEXP (pattern, 0, i);
add_insn_before (insn, before);
}
if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
if (!ggc_p && XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
......@@ -2720,7 +2717,7 @@ emit_insn_after (pattern, after)
add_insn_after (insn, after);
after = insn;
}
if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
if (!ggc_p && XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
......@@ -2868,7 +2865,7 @@ emit_insn (pattern)
insn = XVECEXP (pattern, 0, i);
add_insn (insn);
}
if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
if (!ggc_p && XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
sequence_result[XVECLEN (pattern, 0)] = pattern;
}
else
......@@ -3188,14 +3185,7 @@ start_sequence ()
{
struct sequence_stack *tem;
if (sequence_element_free_list)
{
/* Reuse a previously-saved struct sequence_stack. */
tem = sequence_element_free_list;
sequence_element_free_list = tem->next;
}
else
tem = (struct sequence_stack *) permalloc (sizeof (struct sequence_stack));
tem = (struct sequence_stack *) xmalloc (sizeof (struct sequence_stack));
tem->next = seq_stack;
tem->first = first_insn;
......@@ -3298,8 +3288,7 @@ end_sequence ()
seq_rtl_expr = tem->sequence_rtl_expr;
seq_stack = tem->next;
tem->next = sequence_element_free_list;
sequence_element_free_list = tem;
free (tem);
}
/* Return 1 if currently emitting into a sequence. */
......@@ -3340,14 +3329,18 @@ gen_sequence ()
|| (GET_CODE (first_insn) == CALL_INSN
&& CALL_INSN_FUNCTION_USAGE (first_insn) == NULL_RTX)))
{
NEXT_INSN (first_insn) = free_insn;
free_insn = first_insn;
if (!ggc_p)
{
NEXT_INSN (first_insn) = free_insn;
free_insn = first_insn;
}
return PATTERN (first_insn);
}
/* Put them in a vector. See if we already have a SEQUENCE of the
appropriate length around. */
if (len < SEQUENCE_RESULT_SIZE && (result = sequence_result[len]) != 0)
if (!ggc_p && len < SEQUENCE_RESULT_SIZE
&& (result = sequence_result[len]) != 0)
sequence_result[len] = 0;
else
{
......@@ -3385,7 +3378,6 @@ clear_emit_caches ()
int i;
/* Clear the start_sequence/gen_sequence cache. */
sequence_element_free_list = 0;
for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
sequence_result[i] = 0;
free_insn = 0;
......@@ -3418,17 +3410,15 @@ init_emit ()
f->emit->regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101;
f->emit->regno_pointer_flag
= (char *) xmalloc (f->emit->regno_pointer_flag_length);
bzero (f->emit->regno_pointer_flag, f->emit->regno_pointer_flag_length);
= (char *) xcalloc (f->emit->regno_pointer_flag_length, sizeof (char));
f->emit->regno_pointer_align
= (char *) xmalloc (f->emit->regno_pointer_flag_length);
bzero (f->emit->regno_pointer_align, f->emit->regno_pointer_flag_length);
= (char *) xcalloc (f->emit->regno_pointer_flag_length,
sizeof (char));
regno_reg_rtx
= (rtx *) xmalloc (f->emit->regno_pointer_flag_length * sizeof (rtx));
bzero ((char *) regno_reg_rtx,
f->emit->regno_pointer_flag_length * sizeof (rtx));
= (rtx *) xcalloc (f->emit->regno_pointer_flag_length * sizeof (rtx),
sizeof (rtx));
/* Put copies of all the virtual register rtx into regno_reg_rtx. */
init_virtual_regs (f->emit);
......
......@@ -49,6 +49,7 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "rtl.h"
#include "toplev.h"
#include "ggc.h"
static void encode PROTO((HOST_WIDE_INT *,
HOST_WIDE_INT, HOST_WIDE_INT));
......@@ -1692,29 +1693,32 @@ size_int_wide (number, high, bit_p)
unsigned HOST_WIDE_INT number, high;
int bit_p;
{
register tree t;
/* Type-size nodes already made for small sizes. */
static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1][2];
if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high
&& size_table[number][bit_p] != 0)
return size_table[number][bit_p];
if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high)
{
push_obstacks_nochange ();
/* Make this a permanent node. */
end_temporary_allocation ();
t = build_int_2 (number, 0);
TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
size_table[number][bit_p] = t;
pop_obstacks ();
}
else
tree t;
if (!ggc_p)
{
t = build_int_2 (number, high);
TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
/* Type-size nodes already made for small sizes. */
static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1][2];
if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high
&& size_table[number][bit_p] != 0)
return size_table[number][bit_p];
if (number < 2*HOST_BITS_PER_WIDE_INT + 1 && ! high)
{
push_obstacks_nochange ();
/* Make this a permanent node. */
end_temporary_allocation ();
t = build_int_2 (number, 0);
TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
size_table[number][bit_p] = t;
pop_obstacks ();
return t;
}
}
t = build_int_2 (number, high);
TREE_TYPE (t) = bit_p ? bitsizetype : sizetype;
TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0);
return t;
}
......
......@@ -350,6 +350,7 @@ pop_function_context_from (context)
{
struct function *p = outer_function_chain;
struct var_refs_queue *queue;
struct var_refs_queue *next;
current_function = p;
outer_function_chain = p->next;
......@@ -367,9 +368,14 @@ pop_function_context_from (context)
/* Finish doing put_var_into_stack for any of our variables
which became addressable during the nested function. */
for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
fixup_var_refs (queue->modified, queue->promoted_mode,
queue->unsignedp, 0);
for (queue = p->fixup_var_refs_queue; queue; queue = next)
{
next = queue->next;
fixup_var_refs (queue->modified, queue->promoted_mode,
queue->unsignedp, 0);
free (queue);
}
p->fixup_var_refs_queue = 0;
/* Reset variables that have known state during rtx generation. */
rtx_equal_function_value_matters = 1;
......@@ -1337,20 +1343,13 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
{
struct var_refs_queue *temp;
/* Variable is inherited; fix it up when we get back to its function. */
push_obstacks (function->function_obstack,
function->function_maybepermanent_obstack);
/* See comment in restore_tree_status in tree.c for why this needs to be
on saveable obstack. */
temp
= (struct var_refs_queue *) savealloc (sizeof (struct var_refs_queue));
= (struct var_refs_queue *) xmalloc (sizeof (struct var_refs_queue));
temp->modified = reg;
temp->promoted_mode = promoted_mode;
temp->unsignedp = TREE_UNSIGNED (type);
temp->next = function->fixup_var_refs_queue;
function->fixup_var_refs_queue = temp;
pop_obstacks ();
}
else if (used_p)
/* Variable is local; fix it up now. */
......
......@@ -99,6 +99,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "rtl.h"
#include "insn-config.h" /* For REGISTER_CONSTRAINTS */
#include "ggc.h"
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
......@@ -1726,7 +1727,8 @@ operate_exp (op, left, right)
give the same value), optimize it away. */
if (allsame)
{
obstack_free (rtl_obstack, newexp);
if (!ggc_p)
obstack_free (rtl_obstack, newexp);
return operate_exp (op, left, XEXP (right, 1));
}
......@@ -1734,7 +1736,8 @@ operate_exp (op, left, right)
just use that. */
if (rtx_equal_p (newexp, right))
{
obstack_free (rtl_obstack, newexp);
if (!ggc_p)
obstack_free (rtl_obstack, newexp);
return right;
}
......@@ -1783,7 +1786,8 @@ operate_exp (op, left, right)
optimize it away. */
if (allsame)
{
obstack_free (rtl_obstack, newexp);
if (!ggc_p)
obstack_free (rtl_obstack, newexp);
return operate_exp (op, XEXP (left, 1), right);
}
......@@ -1791,7 +1795,8 @@ operate_exp (op, left, right)
just use that. */
if (rtx_equal_p (newexp, left))
{
obstack_free (rtl_obstack, newexp);
if (!ggc_p)
obstack_free (rtl_obstack, newexp);
return left;
}
......@@ -2609,14 +2614,16 @@ simplify_cond (exp, insn_code, insn_index)
if (len == 0)
{
obstack_free (rtl_obstack, first_spacer);
if (!ggc_p)
obstack_free (rtl_obstack, first_spacer);
if (GET_CODE (defval) == COND)
return simplify_cond (defval, insn_code, insn_index);
return defval;
}
else if (allsame)
{
obstack_free (rtl_obstack, first_spacer);
if (!ggc_p)
obstack_free (rtl_obstack, first_spacer);
return exp;
}
else
......@@ -3146,14 +3153,16 @@ simplify_test_exp (exp, insn_code, insn_index)
SIMPLIFY_ALTERNATIVE (left);
if (left == false_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return false_rtx;
}
right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
SIMPLIFY_ALTERNATIVE (right);
if (left == false_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return false_rtx;
}
......@@ -3185,7 +3194,8 @@ simplify_test_exp (exp, insn_code, insn_index)
if (left == false_rtx || right == false_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return false_rtx;
}
else if (left == true_rtx)
......@@ -3244,14 +3254,16 @@ simplify_test_exp (exp, insn_code, insn_index)
SIMPLIFY_ALTERNATIVE (left);
if (left == true_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return true_rtx;
}
right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
SIMPLIFY_ALTERNATIVE (right);
if (right == true_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return true_rtx;
}
......@@ -3261,7 +3273,8 @@ simplify_test_exp (exp, insn_code, insn_index)
if (right == true_rtx || left == true_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return true_rtx;
}
else if (left == false_rtx)
......@@ -3348,12 +3361,14 @@ simplify_test_exp (exp, insn_code, insn_index)
if (left == false_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return true_rtx;
}
else if (left == true_rtx)
{
obstack_free (rtl_obstack, spacer);
if (!ggc_p)
obstack_free (rtl_obstack, spacer);
return false_rtx;
}
......@@ -3515,7 +3530,8 @@ optimize_attrs ()
insert_insn_ent (av, ie);
something_changed = 1;
}
obstack_free (temp_obstack, spacer);
if (!ggc_p)
obstack_free (temp_obstack, spacer);
}
}
}
......
......@@ -24,6 +24,8 @@
#include "tree.h"
#include "ggc.h"
int ggc_p = 0;
void
lang_mark_tree (t)
union tree_node *t ATTRIBUTE_UNUSED;
......
......@@ -31,6 +31,9 @@
#include "rtl.h"
#include "ggc.h"
/* For now, keep using the old obstack scheme in the gen* programs. */
int ggc_p = 0;
rtx
ggc_alloc_rtx (nslots)
int nslots;
......
......@@ -24,6 +24,7 @@
#include "tree.h"
#include "ggc.h"
#include "flags.h"
#include "varray.h"
/* Debugging flags. */
#undef GGC_DUMP
......@@ -96,6 +97,7 @@ static void ggc_free_rtx PROTO ((struct ggc_rtx *r));
static void ggc_free_tree PROTO ((struct ggc_tree *t));
static void ggc_mark_rtx_ptr PROTO ((void *elt));
static void ggc_mark_tree_ptr PROTO ((void *elt));
static void ggc_mark_tree_varray_ptr PROTO ((void *elt));
/* These allocators are dreadfully simple, with no caching whatsoever so
that Purify-like tools that do allocation versioning can catch errors.
......@@ -472,6 +474,18 @@ ggc_mark_tree (t)
}
}
/* Mark all the elements of the varray V, which contains trees. */
void
ggc_mark_tree_varray (v)
varray_type v;
{
int i;
for (i = v->num_elements - 1; i >= 0; --i)
ggc_mark_tree (VARRAY_TREE (v, i));
}
void
ggc_mark_string (s)
char *s;
......@@ -645,6 +659,17 @@ ggc_add_tree_root (base, nelt)
ggc_add_root (base, nelt, sizeof(tree), ggc_mark_tree_ptr);
}
/* Add vV (a varray full of trees) to the list of GC roots. */
void
ggc_add_tree_varray_root (base, nelt)
varray_type *base;
int nelt;
{
ggc_add_root (base, nelt, sizeof (varray_type),
ggc_mark_tree_varray_ptr);
}
void
ggc_del_root (base)
void *base;
......@@ -681,6 +706,16 @@ ggc_mark_tree_ptr (elt)
ggc_mark_tree (*(tree *)elt);
}
/* Type-correct function to pass to ggc_add_root. It just forwards
ELT (which is really a varray_type *) to ggc_mark_tree_varray. */
static void
ggc_mark_tree_varray_ptr (elt)
void *elt;
{
ggc_mark_tree_varray (*(varray_type *)elt);
}
#ifdef GGC_DUMP
/* Don't enable this unless you want a really really lot of data. */
static void __attribute__((constructor))
......
......@@ -23,6 +23,10 @@
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
/* Language-specific code defines this variable to be either one (if
it wants garbage collection), or zero (if it does not). */
extern int ggc_p;
/* These structures are defined in various headers throughout the
compiler. However, rather than force everyone who includes this
header to include all the headers in which they are declared, we
......@@ -32,6 +36,7 @@ struct eh_status;
struct emit_status;
struct stmt_status;
struct varasm_status;
struct varray_head_tag;
/* Startup */
......@@ -54,6 +59,7 @@ void ggc_add_root PROTO ((void *base, int nelt, int size,
void (*)(void *)));
void ggc_add_rtx_root PROTO ((struct rtx_def **, int nelt));
void ggc_add_tree_root PROTO ((union tree_node **, int nelt));
void ggc_add_tree_varray_root PROTO ((struct varray_head_tag **, int nelt));
void ggc_del_root PROTO ((void *base));
/* Mark nodes from the gc_add_root callback. */
......
......@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "ggc.h"
void print_node ();
void indent_to ();
......@@ -274,7 +275,7 @@ print_node (file, prefix, node, indent)
}
/* If a permanent object is in the wrong obstack, or the reverse, warn. */
if (object_permanent_p (node) != TREE_PERMANENT (node))
if (!ggc_p && object_permanent_p (node) != TREE_PERMANENT (node))
{
if (TREE_PERMANENT (node))
fputs (" !!permanent object in non-permanent obstack!!", file);
......
......@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "real.h"
#include "bitmap.h"
#include "ggc.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
......@@ -244,18 +244,23 @@ rtvec_alloc (n)
int n;
{
rtvec rt;
int i;
rt = (rtvec) obstack_alloc (rtl_obstack,
sizeof (struct rtvec_def)
+ (( n - 1) * sizeof (rtx)));
if (ggc_p)
rt = ggc_alloc_rtvec (n);
else
{
int i;
/* clear out the vector */
PUT_NUM_ELEM (rt, n);
rt = (rtvec) obstack_alloc (rtl_obstack,
sizeof (struct rtvec_def)
+ (( n - 1) * sizeof (rtx)));
for (i = 0; i < n; i++)
rt->elem[i] = 0;
/* clear out the vector */
for (i = 0; i < n; i++)
rt->elem[i] = 0;
}
PUT_NUM_ELEM (rt, n);
return rt;
}
......@@ -267,34 +272,40 @@ rtx_alloc (code)
RTX_CODE code;
{
rtx rt;
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));
if (ggc_p)
rt = ggc_alloc_rtx (GET_RTX_LENGTH (code));
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));
}
PUT_CODE (rt, code);
return rt;
}
......@@ -304,7 +315,8 @@ void
rtx_free (x)
rtx x;
{
obstack_free (rtl_obstack, x);
if (!ggc_p)
obstack_free (rtl_obstack, x);
}
/* Create a new copy of an rtx.
......
......@@ -3801,6 +3801,9 @@ rest_of_compilation (decl)
if (jump_opt_dump)
dump_rtl (".jump", decl, print_rtl, insns);
if (ggc_p)
ggc_collect ();
/* Perform common subexpression elimination.
Nonzero value from `cse_main' means that jumps were simplified
and some code may now be unreachable, so do
......@@ -3846,6 +3849,9 @@ rest_of_compilation (decl)
print_rtl_graph_with_bb (dump_base_name, ".addressof", insns);
}
if (ggc_p)
ggc_collect ();
/* Perform global cse. */
if (optimize > 0 && flag_gcse)
......@@ -3870,6 +3876,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".gcse", insns);
}
if (ggc_p)
ggc_collect ();
}
/* Move constant computations out of loops. */
......@@ -3909,6 +3918,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".loop", insns);
}
if (ggc_p)
ggc_collect ();
}
if (optimize > 0)
......@@ -3953,6 +3965,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".cse2", insns);
}
if (ggc_p)
ggc_collect ();
}
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
......@@ -3972,6 +3987,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".bp", insns);
}
if (ggc_p)
ggc_collect ();
}
/* We are no longer anticipating cse in this function, at least. */
......@@ -4030,6 +4048,9 @@ rest_of_compilation (decl)
print_rtl_graph_with_bb (dump_base_name, ".flow", insns);
}
if (ggc_p)
ggc_collect ();
/* The first life analysis pass has finished. From now on we can not
generate any new pseudos. */
no_new_pseudos = 1;
......@@ -4048,6 +4069,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".combine", insns);
}
if (ggc_p)
ggc_collect ();
}
/* Register allocation pre-pass, to reduce number of moves
......@@ -4066,6 +4090,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".regmove", insns);
}
if (ggc_p)
ggc_collect ();
}
/* Print function header into sched dump now
......@@ -4089,6 +4116,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".sched", insns);
}
if (ggc_p)
ggc_collect ();
}
/* Determine if the current function is a leaf before running reload
......@@ -4126,6 +4156,9 @@ rest_of_compilation (decl)
print_rtl_graph_with_bb (dump_base_name, ".lreg", insns);
}
if (ggc_p)
ggc_collect ();
if (global_reg_dump)
open_dump_file (".greg", decl_printable_name (decl, 2));
......@@ -4145,6 +4178,9 @@ rest_of_compilation (decl)
if (failure)
goto exit_rest_of_compilation;
if (ggc_p)
ggc_collect ();
/* Do a very simple CSE pass over just the hard registers. */
if (optimize > 0)
reload_cse_regs (insns);
......@@ -4203,6 +4239,9 @@ rest_of_compilation (decl)
find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
});
if (ggc_p)
ggc_collect ();
}
flow2_completed = 1;
......@@ -4256,6 +4295,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".sched2", insns);
}
if (ggc_p)
ggc_collect ();
}
#ifdef LEAF_REGISTERS
......@@ -4297,6 +4339,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".mach", insns);
}
if (ggc_p)
ggc_collect ();
#endif
/* If a scheduling pass for delayed branches is to be done,
......@@ -4317,6 +4362,9 @@ rest_of_compilation (decl)
print_rtl_graph_with_bb (dump_base_name, ".dbr", insns);
}
}
if (ggc_p)
ggc_collect ();
#endif
/* Shorten branches. */
......@@ -4337,6 +4385,9 @@ rest_of_compilation (decl)
if (graph_dump_format != no_graph)
print_rtl_graph_with_bb (dump_base_name, ".stack", insns);
}
if (ggc_p)
ggc_collect ();
#endif
/* Now turn the rtl into assembler code. */
......@@ -4373,6 +4424,9 @@ rest_of_compilation (decl)
regset_release_memory ();
});
if (ggc_p)
ggc_collect ();
/* Write DBX symbols if requested */
/* Note that for those inline functions where we don't initially
......@@ -4458,6 +4512,10 @@ rest_of_compilation (decl)
if (! DECL_DEFER_OUTPUT (decl))
free_after_compilation (current_function);
current_function = 0;
ggc_collect ();
/* The parsing time is all the time spent in yyparse
*except* what is spent in this function. */
......
......@@ -474,8 +474,12 @@ void
push_obstacks (current, saveable)
struct obstack *current, *saveable;
{
struct obstack_stack *p
= (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
struct obstack_stack *p;
if (ggc_p)
return;
p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
(sizeof (struct obstack_stack)));
p->current = current_obstack;
......@@ -495,8 +499,12 @@ push_obstacks (current, saveable)
void
push_obstacks_nochange ()
{
struct obstack_stack *p
= (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
struct obstack_stack *p;
if (ggc_p)
return;
p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
(sizeof (struct obstack_stack)));
p->current = current_obstack;
......@@ -512,7 +520,12 @@ push_obstacks_nochange ()
void
pop_obstacks ()
{
struct obstack_stack *p = obstack_stack;
struct obstack_stack *p;
if (ggc_p)
return;
p = obstack_stack;
obstack_stack = p->next;
current_obstack = p->current;
......@@ -1005,8 +1018,13 @@ make_node (code)
abort ();
}
t = (tree) obstack_alloc (obstack, length);
bzero ((PTR) t, length);
if (ggc_p)
t = ggc_alloc_tree (length);
else
{
t = (tree) obstack_alloc (obstack, length);
bzero ((PTR) t, length);
}
#ifdef GATHER_STATISTICS
tree_node_counts[(int)kind]++;
......@@ -1119,8 +1137,13 @@ copy_node (node)
length += (TREE_VEC_LENGTH (node) - 1) * sizeof (char *);
}
t = (tree) obstack_alloc (current_obstack, length);
memcpy (t, node, length);
if (ggc_p)
t = ggc_alloc_tree (length);
else
{
t = (tree) obstack_alloc (current_obstack, length);
memcpy (t, node, length);
}
/* EXPR_WITH_FILE_LOCATION must keep filename info stored in TREE_CHAIN */
if (TREE_CODE (node) != EXPR_WITH_FILE_LOCATION)
......@@ -1230,7 +1253,10 @@ get_identifier (text)
id_string_size += len;
#endif
IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);
if (ggc_p)
IDENTIFIER_POINTER (idp) = ggc_alloc_string (text, len);
else
IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);
TREE_CHAIN (idp) = hash_table[hi];
hash_table[hi] = idp;
......@@ -1469,7 +1495,10 @@ build_string (len, str)
register tree s = make_node (STRING_CST);
TREE_STRING_LENGTH (s) = len;
TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, len);
if (ggc_p)
TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
else
TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, len);
return s;
}
......@@ -1509,8 +1538,13 @@ make_tree_vec (len)
tree_node_sizes[(int)vec_kind] += length;
#endif
t = (tree) obstack_alloc (obstack, length);
bzero ((PTR) t, length);
if (ggc_p)
t = ggc_alloc_tree (length);
else
{
t = (tree) obstack_alloc (obstack, length);
bzero ((PTR) t, length);
}
TREE_SET_CODE (t, TREE_VEC);
TREE_VEC_LENGTH (t) = len;
......@@ -2011,15 +2045,21 @@ tree_cons (purpose, value, chain)
#if 0
register tree node = make_node (TREE_LIST);
#else
register int i;
register tree node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
register tree node;
if (ggc_p)
node = ggc_alloc_tree (sizeof (struct tree_list));
else
{
node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
bzero (node, sizeof (struct tree_common));
}
#ifdef GATHER_STATISTICS
tree_node_counts[(int)x_kind]++;
tree_node_sizes[(int)x_kind] += sizeof (struct tree_list);
#endif
for (i = (sizeof (struct tree_common) / sizeof (int)) - 1; i >= 0; i--)
((int *) node)[i] = 0;
TREE_SET_CODE (node, TREE_LIST);
if (current_obstack == &permanent_obstack)
......@@ -3028,7 +3068,10 @@ build1 (code, type, node)
length = sizeof (struct tree_exp);
t = (tree) obstack_alloc (obstack, length);
if (ggc_p)
t = ggc_alloc_tree (length);
else
t = (tree) obstack_alloc (obstack, length);
bzero ((PTR) t, length);
#ifdef GATHER_STATISTICS
......@@ -3706,7 +3749,8 @@ type_hash_canon (hashcode, type)
t1 = type_hash_lookup (hashcode, type);
if (t1 != 0)
{
obstack_free (TYPE_OBSTACK (type), type);
if (!ggc_p)
obstack_free (TYPE_OBSTACK (type), type);
#ifdef GATHER_STATISTICS
tree_node_counts[(int)t_kind]--;
tree_node_sizes[(int)t_kind] -= sizeof (struct tree_type);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment