diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-09-05 16:08:20 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-09-05 16:08:20 +0000 |
commit | 1bfd55c5832c63621f3f1eac29139cd28f3d17e5 (patch) | |
tree | 53f583f3f8569b93ca268331c1f771e401b63045 | |
parent | 68e99b40dd8701fe7d675acb9cdff108e5ad630a (diff) | |
download | gcc-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/ChangeLog | 60 | ||||
-rw-r--r-- | gcc/Makefile.in | 11 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 58 | ||||
-rw-r--r-- | gcc/fold-const.c | 46 | ||||
-rw-r--r-- | gcc/function.c | 21 | ||||
-rw-r--r-- | gcc/genattrtab.c | 46 | ||||
-rw-r--r-- | gcc/ggc-callbacks.c | 2 | ||||
-rw-r--r-- | gcc/ggc-none.c | 3 | ||||
-rw-r--r-- | gcc/ggc-simple.c | 35 | ||||
-rw-r--r-- | gcc/ggc.h | 6 | ||||
-rw-r--r-- | gcc/print-tree.c | 3 | ||||
-rw-r--r-- | gcc/rtl.c | 84 | ||||
-rw-r--r-- | gcc/toplev.c | 58 | ||||
-rw-r--r-- | gcc/tree.c | 82 |
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); |