summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1999-09-05 16:08:20 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1999-09-05 16:08:20 +0000
commit1bfd55c5832c63621f3f1eac29139cd28f3d17e5 (patch)
tree53f583f3f8569b93ca268331c1f771e401b63045
parent68e99b40dd8701fe7d675acb9cdff108e5ad630a (diff)
downloadgcc-1bfd55c5832c63621f3f1eac29139cd28f3d17e5.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@29125 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog60
-rw-r--r--gcc/Makefile.in11
-rw-r--r--gcc/emit-rtl.c58
-rw-r--r--gcc/fold-const.c46
-rw-r--r--gcc/function.c21
-rw-r--r--gcc/genattrtab.c46
-rw-r--r--gcc/ggc-callbacks.c2
-rw-r--r--gcc/ggc-none.c3
-rw-r--r--gcc/ggc-simple.c35
-rw-r--r--gcc/ggc.h6
-rw-r--r--gcc/print-tree.c3
-rw-r--r--gcc/rtl.c84
-rw-r--r--gcc/toplev.c58
-rw-r--r--gcc/tree.c82
14 files changed, 373 insertions, 142 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3e239beae31..6954e886c73 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,63 @@
+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
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 789bd0b434b..d60242e8a9a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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)
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 0b2c10de070..a87c5198ca0 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -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);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3cde5f539b0..f7dc9cb53e8 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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;
}
diff --git a/gcc/function.c b/gcc/function.c
index b0c27256dab..960b660eca9 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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. */
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index a958025cb2b..254f78c2459 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -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);
}
}
}
diff --git a/gcc/ggc-callbacks.c b/gcc/ggc-callbacks.c
index 1b19579e914..797c3de47ca 100644
--- a/gcc/ggc-callbacks.c
+++ b/gcc/ggc-callbacks.c
@@ -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;
diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
index 5fff1045fab..0953059a41c 100644
--- a/gcc/ggc-none.c
+++ b/gcc/ggc-none.c
@@ -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;
diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c
index 1d0432d8940..0e7b53fc185 100644
--- a/gcc/ggc-simple.c
+++ b/gcc/ggc-simple.c
@@ -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))
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 6967900cb8a..557ee064d79 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -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. */
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 55eb4c8a8b2..81219e77de3 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -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);
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 4b14dabf5cc..db28096ac65 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -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.
diff --git a/gcc/toplev.c b/gcc/toplev.c
index becdfe06c49..ca95121e62d 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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. */
diff --git a/gcc/tree.c b/gcc/tree.c
index 1d0f27377da..03fc790d2b4 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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);