+Sat Oct 18 13:47:15 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (restore_tree_status): Also free up temporary storage
+ when we finish a toplevel function.
+ (dump_tree_statistics): Print stats for backend obstacks.
+
Sat Oct 18 12:47:31 1997 Doug Evans <dje@canuck.cygnus.com>
* expr.c (use_group_regs): Don't call use_reg for MEMs.
+Sat Oct 18 09:49:46 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * libgcc2.c (__throw): Don't copy the return address.
+ * dwarf2out.c (expand_builtin_dwarf_reg_size): Ignore return address.
+
+ * except.c (exceptions_via_longjmp): Initialize to 2 (uninitialized).
+ * toplev.c (main): Initialize exceptions_via_longjmp.
+
+ * tree.c: Add extra_inline_obstacks.
+ (save_tree_status): Use it.
+ (restore_tree_status): If this is a toplevel inline obstack and we
+ didn't want to save anything on it, recycle it.
+ (print_inline_obstack_statistics): New fn.
+ * function.c (pop_function_context_from): Pass context to
+ restore_tree_status.
+ * obstack.h (obstack_empty_p): New macro.
+
Sat Oct 18 00:43:59 1997 Jeffrey A Law (law@cygnus.com)
* i386/freebsd.h (ASM_COMMENT_START): Fix.
tree reg_tree;
rtx target;
{
- int i, n_ranges, size;
+ int size;
struct reg_size_range ranges[5];
tree t, t2;
- ranges[0].beg = 0;
- ranges[0].size = GET_MODE_SIZE (reg_raw_mode[0]);
- n_ranges = 1;
+ int i = 0;
+ int n_ranges = 0;
+ int last_size = -1;
- for (i = 1; i < FIRST_PSEUDO_REGISTER; ++i)
+ for (; i < FIRST_PSEUDO_REGISTER; ++i)
{
+ /* The return address is out of order on the MIPS, and we don't use
+ copy_reg for it anyway, so we don't care here how large it is. */
+ if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
+ continue;
+
size = GET_MODE_SIZE (reg_raw_mode[i]);
- if (size != ranges[n_ranges-1].size)
+ if (size != last_size)
{
- ranges[n_ranges-1].end = i-1;
ranges[n_ranges].beg = i;
- ranges[n_ranges].size = GET_MODE_SIZE (reg_raw_mode[i]);
+ ranges[n_ranges].size = last_size = GET_MODE_SIZE (reg_raw_mode[i]);
++n_ranges;
assert (n_ranges < 5);
}
+ ranges[n_ranges-1].end = i;
}
- ranges[n_ranges-1].end = i-1;
/* The usual case: fp regs surrounded by general regs. */
if (n_ranges == 3 && ranges[0].size == ranges[2].size)
struct simple_obstack_stack *toplev_inline_obstacks;
+/* Former elements of toplev_inline_obstacks that have been recycled. */
+
+struct simple_obstack_stack *extra_inline_obstacks;
+
/* This is a list of function_maybepermanent_obstacks for inline functions
nested in the current function that were compiled in the middle of
compiling other functions. */
head = &f->inline_obstacks;
}
- current = ((struct simple_obstack_stack *)
- xmalloc (sizeof (struct simple_obstack_stack)));
+ if (context == NULL_TREE && extra_inline_obstacks)
+ {
+ current = extra_inline_obstacks;
+ extra_inline_obstacks = current->next;
+ }
+ else
+ {
+ current = ((struct simple_obstack_stack *)
+ xmalloc (sizeof (struct simple_obstack_stack)));
+
+ current->obstack
+ = (struct obstack *) xmalloc (sizeof (struct obstack));
+ gcc_obstack_init (current->obstack);
+ }
- current->obstack = (struct obstack *) xmalloc (sizeof (struct obstack));
function_maybepermanent_obstack = current->obstack;
- gcc_obstack_init (function_maybepermanent_obstack);
current->next = *head;
*head = current;
This is used after a nested function. */
void
-restore_tree_status (p)
+restore_tree_status (p, context)
struct function *p;
+ tree context;
{
all_types_permanent = p->all_types_permanent;
momentary_stack = p->momentary_stack;
past the nested function's end. */
obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
+ /* If we were compiling a toplevel function, we can free this space now. */
+ if (context == NULL_TREE)
+ {
+ obstack_free (&temporary_obstack, temporary_firstobj);
+ obstack_free (&momentary_obstack, momentary_function_firstobj);
+ }
+
+ /* If we were compiling a toplevel function that we don't actually want
+ to save anything from, return the obstack to the pool. */
+ if (context == NULL_TREE
+ && obstack_empty_p (function_maybepermanent_obstack))
+ {
+ struct simple_obstack_stack *current, **p = &toplev_inline_obstacks;
+
+ while ((*p)->obstack != function_maybepermanent_obstack)
+ p = &((*p)->next);
+ current = *p;
+ *p = current->next;
+
+ current->next = extra_inline_obstacks;
+ extra_inline_obstacks = current;
+ }
+
obstack_free (function_obstack, 0);
free (function_obstack);
return NULL_TREE;
}
+/* Print debugging information about the size of the
+ toplev_inline_obstacks. */
+
+void
+print_inline_obstack_statistics ()
+{
+ struct simple_obstack_stack *current = toplev_inline_obstacks;
+ int n_obstacks = 0;
+ unsigned long n_alloc = 0;
+ int n_chunks = 0;
+
+ for (; current; current = current->next, ++n_obstacks)
+ {
+ struct obstack *o = current->obstack;
+ struct _obstack_chunk *chunk = o->chunk;
+
+ n_alloc += o->next_free - chunk->contents;
+ chunk = chunk->prev;
+ ++n_chunks;
+ for (; chunk; chunk = chunk->prev, ++n_chunks)
+ n_alloc += chunk->limit - &chunk->contents[0];
+ }
+ fprintf (stderr, "inline obstacks: %d obstacks, %lu bytes, %d chunks\n",
+ n_obstacks, n_alloc, n_chunks);
+}
+
+/* Print debugging information about the obstack O, named STR. */
+
void
print_obstack_statistics (str, o)
char *str;
struct obstack *o;
{
struct _obstack_chunk *chunk = o->chunk;
- int n_chunks = 0;
- int n_alloc = 0;
+ int n_chunks = 1;
+ unsigned long n_alloc = 0;
+ n_alloc += o->next_free - chunk->contents;
+ chunk = chunk->prev;
while (chunk)
{
n_chunks += 1;
n_alloc += chunk->limit - &chunk->contents[0];
chunk = chunk->prev;
}
- fprintf (stderr, "obstack %s: %d bytes, %d chunks\n",
+ fprintf (stderr, "obstack %s: %lu bytes, %d chunks\n",
str, n_alloc, n_chunks);
}
+
+/* Print debugging information about tree nodes generated during the compile,
+ and any language-specific information. */
+
void
dump_tree_statistics ()
{
#else
fprintf (stderr, "(No per-node statistics)\n");
#endif
+ print_obstack_statistics ("permanent_obstack", &permanent_obstack);
+ print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
+ print_obstack_statistics ("temporary_obstack", &temporary_obstack);
+ print_obstack_statistics ("momentary_obstack", &momentary_obstack);
+ print_obstack_statistics ("temp_decl_obstack", &temp_decl_obstack);
+ print_inline_obstack_statistics ();
print_lang_statistics ();
}
\f