diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5b81e158e4a..3e39ae7c08c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +Wed Aug 25 13:41:47 EDT 1999 Andrew MacLeod + + * lists.c (unused_insn_list, unused_expr_list): New file for + maintaining various types of lists. New statics for maintaining a + cache of available INSN_LIST and EXPR_LIST nodes. + (free_list): Static function for freeing a list of INSN/EXPR nodes. + (alloc_INSN_LIST): Function to get a free INSN_LIST node. + (alloc_EXPR_LIST): Function to get a free EXPR_LIST node. + (init_EXPR_INSN_LIST_cache): Initialize the cache lists. + (free_EXPR_LIST_list): Free an entire list of EXPR_LIST nodes. + (free_INSN_LIST_list): Free an entire list of INSN_LIST nodes. + (free_EXPR_LIST_node): Free an individual EXPR_LIST node. + (free_INSN_LIST_node): Free an individual INSN_LIST node. + * haifa-sched.c (unused_insn_list, unused_expr_list): Moved to flow.c + (free_list, alloc_INSN_LIST, alloc_EXPR_LIST): Moved to flow.c + (remove_dependence, free_pending_lists): Use new global routines. + (flush_pending_lists, sched_analyze_insn): Use new global routines. + (sched_analyze, compute_block_backward_dependences): Use new routines. + (sched_analyze_1, sched_analyze_2): Use new routines. + (schedule_insns): Use new global routines. + * rtl.h (init_EXPR_INSN_LIST_cache, free_EXPR_LIST_list): Add function + prototypes. + (free_INSN_LIST_list, free_EXPR_LIST_node): Add prototypes. + (free_INSN_LIST_node, alloc_INSN_LIST, alloc_EXPR_LIST): Add function + prototypes. + * toplev.c (rest_of_compilation): Initialize node cache. + * Makefile.in (OBJS): Add lists.o to list of object files. + (lists.o): Add dependancies. + Wed Aug 25 17:31:56 1999 Nick Clifton * config/v850/v850.md: Fix compile time warning messages. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index bc424b13de1..2fcffc2d925 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -667,7 +667,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ insn-peep.o reorg.o haifa-sched.o final.o recog.o reg-stack.o \ insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \ profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \ - mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o + mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o lists.o # GEN files are listed separately, so they can be built before doing parallel # makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load @@ -1581,6 +1581,7 @@ reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) recog.h \ $(REGS_H) hard-reg-set.h flags.h insn-config.h insn-flags.h toplev.h \ function.h dyn-string.o: dyn-string.c dyn-string.h $(CONFIG_H) system.h +lists.o: lists.c $(CONFIG_H) system.h toplev.h $(RTL_H) $(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) \ $(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \ diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 5638592e17d..42f44b7cad6 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -766,82 +766,6 @@ static void schedule_region PROTO ((int)); #define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X))) -/* Helper functions for instruction scheduling. */ - -/* An INSN_LIST containing all INSN_LISTs allocated but currently unused. */ -static rtx unused_insn_list; - -/* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused. */ -static rtx unused_expr_list; - -static void free_list PROTO ((rtx *, rtx *)); -static rtx alloc_INSN_LIST PROTO ((rtx, rtx)); -static rtx alloc_EXPR_LIST PROTO ((int, rtx, rtx)); - -static void -free_list (listp, unused_listp) - rtx *listp, *unused_listp; -{ - register rtx link, prev_link; - - if (*listp == 0) - return; - - prev_link = *listp; - link = XEXP (prev_link, 1); - - while (link) - { - prev_link = link; - link = XEXP (link, 1); - } - - XEXP (prev_link, 1) = *unused_listp; - *unused_listp = *listp; - *listp = 0; -} - -static rtx -alloc_INSN_LIST (val, next) - rtx val, next; -{ - rtx r; - - if (unused_insn_list) - { - r = unused_insn_list; - unused_insn_list = XEXP (r, 1); - XEXP (r, 0) = val; - XEXP (r, 1) = next; - PUT_REG_NOTE_KIND (r, VOIDmode); - } - else - r = gen_rtx_INSN_LIST (VOIDmode, val, next); - - return r; -} - -static rtx -alloc_EXPR_LIST (kind, val, next) - int kind; - rtx val, next; -{ - rtx r; - - if (unused_expr_list) - { - r = unused_expr_list; - unused_expr_list = XEXP (r, 1); - XEXP (r, 0) = val; - XEXP (r, 1) = next; - PUT_REG_NOTE_KIND (r, kind); - } - else - r = gen_rtx_EXPR_LIST (kind, val, next); - - return r; -} - /* Add ELEM wrapped in an INSN_LIST with reg note kind DEP_TYPE to the LOG_LINKS of INSN, if not already there. DEP_TYPE indicates the type of dependence that this link represents. */ @@ -949,9 +873,7 @@ remove_dependence (insn, elem) XEXP (prev, 1) = next; else LOG_LINKS (insn) = next; - - XEXP (link, 1) = unused_insn_list; - unused_insn_list = link; + free_INSN_LIST_node (link); found = 1; } @@ -3226,10 +3148,10 @@ free_pending_lists () { if (current_nr_blocks <= 1) { - free_list (&pending_read_insns, &unused_insn_list); - free_list (&pending_write_insns, &unused_insn_list); - free_list (&pending_read_mems, &unused_expr_list); - free_list (&pending_write_mems, &unused_expr_list); + free_INSN_LIST_list (&pending_read_insns); + free_INSN_LIST_list (&pending_write_insns); + free_EXPR_LIST_list (&pending_read_mems); + free_EXPR_LIST_list (&pending_write_mems); } else { @@ -3238,10 +3160,10 @@ free_pending_lists () for (bb = 0; bb < current_nr_blocks; bb++) { - free_list (&bb_pending_read_insns[bb], &unused_insn_list); - free_list (&bb_pending_write_insns[bb], &unused_insn_list); - free_list (&bb_pending_read_mems[bb], &unused_expr_list); - free_list (&bb_pending_write_mems[bb], &unused_expr_list); + free_INSN_LIST_list (&bb_pending_read_insns[bb]); + free_INSN_LIST_list (&bb_pending_write_insns[bb]); + free_EXPR_LIST_list (&bb_pending_read_mems[bb]); + free_EXPR_LIST_list (&bb_pending_write_mems[bb]); } } } @@ -3284,13 +3206,11 @@ flush_pending_lists (insn, only_write) link = pending_read_insns; pending_read_insns = XEXP (pending_read_insns, 1); - XEXP (link, 1) = unused_insn_list; - unused_insn_list = link; + free_INSN_LIST_node (link); link = pending_read_mems; pending_read_mems = XEXP (pending_read_mems, 1); - XEXP (link, 1) = unused_expr_list; - unused_expr_list = link; + free_EXPR_LIST_node (link); } while (pending_write_insns) { @@ -3298,13 +3218,11 @@ flush_pending_lists (insn, only_write) link = pending_write_insns; pending_write_insns = XEXP (pending_write_insns, 1); - XEXP (link, 1) = unused_insn_list; - unused_insn_list = link; + free_INSN_LIST_node (link); link = pending_write_mems; pending_write_mems = XEXP (pending_write_mems, 1); - XEXP (link, 1) = unused_expr_list; - unused_expr_list = link; + free_EXPR_LIST_node (link); } pending_lists_length = 0; @@ -3312,7 +3230,7 @@ flush_pending_lists (insn, only_write) for (u = last_pending_memory_flush; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI); - free_list (&last_pending_memory_flush, &unused_insn_list); + free_INSN_LIST_list (&last_pending_memory_flush); last_pending_memory_flush = alloc_INSN_LIST (insn, NULL_RTX); } @@ -3379,7 +3297,7 @@ sched_analyze_1 (x, insn) but sets must be ordered with respect to a pending clobber. */ if (code == SET) { - free_list (®_last_uses[regno + i], &unused_insn_list); + free_INSN_LIST_list (®_last_uses[regno + i]); for (u = reg_last_clobbers[regno + i]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), REG_DEP_OUTPUT); SET_REGNO_REG_SET (reg_pending_sets, regno + i); @@ -3406,7 +3324,7 @@ sched_analyze_1 (x, insn) if (code == SET) { - free_list (®_last_uses[regno], &unused_insn_list); + free_INSN_LIST_list (®_last_uses[regno]); for (u = reg_last_clobbers[regno]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), REG_DEP_OUTPUT); SET_REGNO_REG_SET (reg_pending_sets, regno); @@ -3672,7 +3590,7 @@ sched_analyze_2 (x, insn) { for (u = reg_last_uses[i]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI); - free_list (®_last_uses[i], &unused_insn_list); + free_INSN_LIST_list (®_last_uses[i]); for (u = reg_last_sets[i]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), 0); @@ -3805,7 +3723,7 @@ sched_analyze_insn (x, insn, loop_notes) rtx u; for (u = reg_last_uses[i]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI); - free_list (®_last_uses[i], &unused_insn_list); + free_INSN_LIST_list (®_last_uses[i]); for (u = reg_last_sets[i]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), 0); @@ -3825,9 +3743,8 @@ sched_analyze_insn (x, insn, loop_notes) subsequent sets will be output dependant on it. */ EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i, { - free_list (®_last_sets[i], &unused_insn_list); - free_list (®_last_clobbers[i], - &unused_insn_list); + free_INSN_LIST_list (®_last_sets[i]); + free_INSN_LIST_list (®_last_clobbers[i]); reg_last_sets[i] = alloc_INSN_LIST (insn, NULL_RTX); }); @@ -3843,7 +3760,7 @@ sched_analyze_insn (x, insn, loop_notes) { for (i = 0; i < maxreg; i++) { - free_list (®_last_sets[i], &unused_insn_list); + free_INSN_LIST_list (®_last_sets[i]); reg_last_sets[i] = alloc_INSN_LIST (insn, NULL_RTX); } @@ -3937,7 +3854,7 @@ sched_analyze (head, tail) { for (u = reg_last_uses[i]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI); - free_list (®_last_uses[i], &unused_insn_list); + free_INSN_LIST_list (®_last_uses[i]); for (u = reg_last_sets[i]; u; u = XEXP (u, 1)) add_dependence (insn, XEXP (u, 0), 0); @@ -3995,7 +3912,7 @@ sched_analyze (head, tail) function call) on all hard register clobberage. */ /* last_function_call is now a list of insns */ - free_list(&last_function_call, &unused_insn_list); + free_INSN_LIST_list(&last_function_call); last_function_call = alloc_INSN_LIST (insn, NULL_RTX); } @@ -7455,18 +7372,18 @@ compute_block_backward_dependences (bb) /* Free up the INSN_LISTs Note this loop is executed max_reg * nr_regions times. It's first - implementation accounted for over 90% of the calls to free_list. - The list was empty for the vast majority of those calls. On the PA, - not calling free_list in those cases improves -O2 compile times by + implementation accounted for over 90% of the calls to free_INSN_LIST_list. + The list was empty for the vast majority of those calls. On the PA, not + calling free_INSN_LIST_list in those cases improves -O2 compile times by 3-5% on average. */ for (b = 0; b < max_reg; ++b) { if (reg_last_clobbers[b]) - free_list (®_last_clobbers[b], &unused_insn_list); + free_INSN_LIST_list (®_last_clobbers[b]); if (reg_last_sets[b]) - free_list (®_last_sets[b], &unused_insn_list); + free_INSN_LIST_list (®_last_sets[b]); if (reg_last_uses[b]) - free_list (®_last_uses[b], &unused_insn_list); + free_INSN_LIST_list (®_last_uses[b]); } /* Assert that we won't need bb_reg_last_* for this block anymore. */ @@ -7823,18 +7740,6 @@ schedule_insns (dump_file) nr_inter = 0; nr_spec = 0; - /* Initialize the unused_*_lists. We can't use the ones left over from - the previous function, because gcc has freed that memory. We can use - the ones left over from the first sched pass in the second pass however, - so only clear them on the first sched pass. The first pass is before - reload if flag_schedule_insns is set, otherwise it is afterwards. */ - - if (reload_completed == 0 || !flag_schedule_insns) - { - unused_insn_list = 0; - unused_expr_list = 0; - } - /* initialize issue_rate */ issue_rate = ISSUE_RATE; diff --git a/gcc/lists.c b/gcc/lists.c new file mode 100644 index 00000000000..331b9538b3d --- /dev/null +++ b/gcc/lists.c @@ -0,0 +1,150 @@ +/* List management for the GNU C-Compiler expander. + Copyright (C) 1987, 88, 92-97, 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "toplev.h" +#include "rtl.h" + +/* Functions for maintaining cache-able lists of EXPR_LIST and INSN_LISTs. */ + +/* An INSN_LIST containing all INSN_LISTs allocated but currently unused. */ +static rtx unused_insn_list; + +/* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused. */ +static rtx unused_expr_list; + + +/* This function will free an entire list of either EXPR_LIST or INSN_LIST + nodes. This is to be used only only lists that consist exclusively of + nodes of one type only. This is only called by free_EXPR_LIST_list + and free_INSN_LIST_list. */ +static void +free_list (listp, unused_listp) + rtx *listp, *unused_listp; +{ + register rtx link, prev_link; + + prev_link = *listp; + link = XEXP (prev_link, 1); + + while (link) + { + prev_link = link; + link = XEXP (link, 1); + } + + XEXP (prev_link, 1) = *unused_listp; + *unused_listp = *listp; + *listp = 0; +} + +/* This call is used in place of a gen_rtx_INSN_LIST. If there is a cached + node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST + is made. */ +rtx +alloc_INSN_LIST (val, next) + rtx val, next; +{ + rtx r; + + if (unused_insn_list) + { + r = unused_insn_list; + unused_insn_list = XEXP (r, 1); + XEXP (r, 0) = val; + XEXP (r, 1) = next; + PUT_REG_NOTE_KIND (r, VOIDmode); + } + else + r = gen_rtx_INSN_LIST (VOIDmode, val, next); + + return r; +} + +/* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached + node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST + is made. */ +rtx +alloc_EXPR_LIST (kind, val, next) + int kind; + rtx val, next; +{ + rtx r; + + if (unused_expr_list) + { + r = unused_expr_list; + unused_expr_list = XEXP (r, 1); + XEXP (r, 0) = val; + XEXP (r, 1) = next; + PUT_REG_NOTE_KIND (r, kind); + } + else + r = gen_rtx_EXPR_LIST (kind, val, next); + + return r; +} + +/* This function will initialize the EXPR_LIST and INSN_LIST caches. */ +void +init_EXPR_INSN_LIST_cache () +{ + unused_expr_list = NULL; + unused_insn_list = NULL; +} + +/* This function will free up an entire list of EXPR_LIST nodes. */ +void +free_EXPR_LIST_list (listp) + rtx *listp; +{ + if (*listp == 0) + return; + free_list (listp, &unused_expr_list); +} + +/* This function will free up an entire list of INSN_LIST nodes. */ +void +free_INSN_LIST_list (listp) + rtx *listp; +{ + if (*listp == 0) + return; + free_list (listp, &unused_insn_list); +} + +/* This function will free up an individual EXPR_LIST node. */ +void +free_EXPR_LIST_node (ptr) + rtx ptr; +{ + XEXP (ptr, 1) = unused_expr_list; + unused_expr_list = ptr; +} + +/* This function will free up an individual INSN_LIST node. */ +void +free_INSN_LIST_node (ptr) + rtx ptr; +{ + XEXP (ptr, 1) = unused_insn_list; + unused_insn_list = ptr; +} diff --git a/gcc/rtl.h b/gcc/rtl.h index 40a3125342f..3c8a1924eb5 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1022,6 +1022,13 @@ extern void remove_node_from_expr_list PROTO((rtx, rtx *)); /* flow.c */ extern rtx find_use_as_address PROTO((rtx, rtx, HOST_WIDE_INT)); +void init_EXPR_INSN_LIST_cache PROTO((void)); +void free_EXPR_LIST_list PROTO((rtx *)); +void free_INSN_LIST_list PROTO((rtx *)); +void free_EXPR_LIST_node PROTO((rtx)); +void free_INSN_LIST_node PROTO((rtx)); +rtx alloc_INSN_LIST PROTO((rtx, rtx)); +rtx alloc_EXPR_LIST PROTO((int, rtx, rtx)); /* regclass.c */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 1f831b7b225..19b98333248 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -3821,6 +3821,8 @@ rest_of_compilation (decl) unshare_all_rtl (insns); + init_EXPR_INSN_LIST_cache (); + #ifdef SETJMP_VIA_SAVE_AREA /* This must be performed before virutal register instantiation. */ if (current_function_calls_alloca)