From 7fb47f9f1adf513b1b2b5798de845536228fe16d Mon Sep 17 00:00:00 2001 From: hubicka Date: Tue, 30 Oct 2001 11:13:49 +0000 Subject: * lcm.c (optimize_mode_switching): Do not rebuild liveness information when no changes has been made. * gcse.c (reg_set_bitmap): Turn into reg_set. (modify_mem_list_set, canon_modify_mem_list_set) (clear_modify_mem_tables, free_modify_mem_tables): New. (gcse_main); Use free_modify_mem_tables. (free_gcse_mem): Likewise; free the bitmaps. (alloc_gcse_main): Initialize the bitmaps. (canon_list_insert): Set canon_modify_mem_list_set. (record_last_mem_set_info): Likewise; set modify_mem_list_set. (compute_hash_table): Use clear_modify_mem_tables. (reset_opr_set_tables): Likewise. (oprs_not_set_p): reg_set_bitmap is regset. (mark_set, mark_clobber): Likewise. * df.h (DF_EQUIV_NOTES): New constant. (df_insn_refs_record): Record uses inside or REG_EQUIV/EQUAL notes when asked for. * sched-rgn.c (CHECK_DEAD_NOTES): New constant. (init_regions, schedule_insns): Conditionalize the checking code by CHECK_DEAD_NOTES; avoid multiple calls to update_life_info. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46634 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 26 ++++++++++++++ gcc/df.c | 17 +++++++++ gcc/df.h | 1 + gcc/gcse.c | 106 +++++++++++++++++++++++++++----------------------------- gcc/lcm.c | 22 ++++++++++++ gcc/reg-stack.c | 8 +++-- gcc/sched-rgn.c | 85 ++++++++++++++++++++++++++++----------------- 7 files changed, 176 insertions(+), 89 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f0659d23aa7..a7e6c7a4d30 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +Tue Oct 30 11:08:11 CET 2001 Jan Hubicka + + * lcm.c (optimize_mode_switching): Do not rebuild liveness information + when no changes has been made. + + * gcse.c (reg_set_bitmap): Turn into reg_set. + (modify_mem_list_set, canon_modify_mem_list_set) + (clear_modify_mem_tables, free_modify_mem_tables): New. + (gcse_main); Use free_modify_mem_tables. + (free_gcse_mem): Likewise; free the bitmaps. + (alloc_gcse_main): Initialize the bitmaps. + (canon_list_insert): Set canon_modify_mem_list_set. + (record_last_mem_set_info): Likewise; set modify_mem_list_set. + (compute_hash_table): Use clear_modify_mem_tables. + (reset_opr_set_tables): Likewise. + (oprs_not_set_p): reg_set_bitmap is regset. + (mark_set, mark_clobber): Likewise. + + * df.h (DF_EQUIV_NOTES): New constant. + (df_insn_refs_record): Record uses inside or REG_EQUIV/EQUAL notes + when asked for. + + * sched-rgn.c (CHECK_DEAD_NOTES): New constant. + (init_regions, schedule_insns): Conditionalize the checking + code by CHECK_DEAD_NOTES; avoid multiple calls to update_life_info. + Tue Oct 30 11:02:31 CET 2001 Jan Hubicka * i386.md (movti_rex64 splitter): Fix condition. diff --git a/gcc/df.c b/gcc/df.c index 75148733e59..3318d456a55 100644 --- a/gcc/df.c +++ b/gcc/df.c @@ -1224,8 +1224,25 @@ df_insn_refs_record (df, bb, insn) if (INSN_P (insn)) { + rtx note; + /* Record register defs */ df_defs_record (df, PATTERN (insn), bb, insn); + + if (df->flags & DF_EQUIV_NOTES) + for (note = REG_NOTES (insn); note; + note = XEXP (note, 1)) + { + switch (REG_NOTE_KIND (note)) + { + case REG_EQUIV: + case REG_EQUAL: + df_uses_record (df, &XEXP (note, 0), DF_REF_REG_USE, + bb, insn); + default: + break; + } + } if (GET_CODE (insn) == CALL_INSN) { diff --git a/gcc/df.h b/gcc/df.h index 068461d8ac4..395b325d516 100644 --- a/gcc/df.h +++ b/gcc/df.h @@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define DF_RU_CHAIN 128 /* Reg-use chain. */ #define DF_ALL 255 #define DF_HARD_REGS 1024 +#define DF_EQUIV_NOTES 2048 /* Mark uses present in EQUIV/EQUAL notes. */ enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD, DF_REF_REG_MEM_STORE}; diff --git a/gcc/gcse.c b/gcc/gcse.c index a6cd29e092e..a91cfd6836e 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -481,7 +481,7 @@ static struct ls_expr * pre_ldst_mems = NULL; /* Bitmap containing one bit for each register in the program. Used when performing GCSE to track which registers have been set since the start of the basic block. */ -static sbitmap reg_set_bitmap; +static regset reg_set_bitmap; /* For each block, a bitmap of registers set in the block. This is used by expr_killed_p and compute_transp. @@ -493,9 +493,11 @@ static sbitmap *reg_set_in_block; /* Array, indexed by basic block number for a list of insns which modify memory within that block. */ static rtx * modify_mem_list; +bitmap modify_mem_list_set; /* This array parallels modify_mem_list, but is kept canonicalized. */ static rtx * canon_modify_mem_list; +bitmap canon_modify_mem_list_set; /* Various variables for statistics gathering. */ /* Memory used in a pass. @@ -693,6 +695,8 @@ static void delete_store PARAMS ((struct ls_expr *, basic_block)); static void free_store_memory PARAMS ((void)); static void store_motion PARAMS ((void)); +static void clear_modify_mem_tables PARAMS ((void)); +static void free_modify_mem_tables PARAMS ((void)); /* Entry point for global common subexpression elimination. F is the first instruction in the function. */ @@ -825,15 +829,7 @@ gcse_main (f, file) basic blocks. */ if (changed) { - int i; - - for (i = 0; i < orig_bb_count; i++) - { - if (modify_mem_list[i]) - free_INSN_LIST_list (modify_mem_list + i); - if (canon_modify_mem_list[i]) - free_INSN_LIST_list (canon_modify_mem_list + i); - } + free_modify_mem_tables (); modify_mem_list = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx *)); canon_modify_mem_list @@ -1016,7 +1012,7 @@ alloc_gcse_mem (f) CUID_INSN (i++) = insn; /* Allocate vars to track sets of regs. */ - reg_set_bitmap = (sbitmap) sbitmap_alloc (max_gcse_regno); + reg_set_bitmap = BITMAP_XMALLOC (); /* Allocate vars to track sets of regs, memory per block. */ reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, @@ -1027,6 +1023,8 @@ alloc_gcse_mem (f) canon_modify_mem_list = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx *)); memset ((char *) modify_mem_list, 0, n_basic_blocks * sizeof (rtx *)); memset ((char *) canon_modify_mem_list, 0, n_basic_blocks * sizeof (rtx *)); + modify_mem_list_set = BITMAP_XMALLOC (); + canon_modify_mem_list_set = BITMAP_XMALLOC (); } /* Free memory allocated by alloc_gcse_mem. */ @@ -1037,26 +1035,12 @@ free_gcse_mem () free (uid_cuid); free (cuid_insn); - free (reg_set_bitmap); + BITMAP_XFREE (reg_set_bitmap); sbitmap_vector_free (reg_set_in_block); - /* re-Cache any INSN_LIST nodes we have allocated. */ - { - int i; - - for (i = 0; i < n_basic_blocks; i++) - { - if (modify_mem_list[i]) - free_INSN_LIST_list (modify_mem_list + i); - if (canon_modify_mem_list[i]) - free_INSN_LIST_list (canon_modify_mem_list + i); - } - - free (modify_mem_list); - free (canon_modify_mem_list); - modify_mem_list = 0; - canon_modify_mem_list = 0; - } + free_modify_mem_tables (); + BITMAP_XFREE (modify_mem_list_set); + BITMAP_XFREE (canon_modify_mem_list_set); } /* Many of the global optimization algorithms work by solving dataflow @@ -2403,6 +2387,7 @@ canon_list_insert (dest, unused1, v_insn) alloc_INSN_LIST (dest_addr, canon_modify_mem_list[BLOCK_NUM (insn)]); canon_modify_mem_list[BLOCK_NUM (insn)] = alloc_INSN_LIST (dest, canon_modify_mem_list[BLOCK_NUM (insn)]); + bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn)); } /* Record memory modification information for INSN. We do not actually care @@ -2417,6 +2402,7 @@ record_last_mem_set_info (insn) everything. */ modify_mem_list[BLOCK_NUM (insn)] = alloc_INSN_LIST (insn, modify_mem_list[BLOCK_NUM (insn)]); + bitmap_set_bit (modify_mem_list_set, BLOCK_NUM (insn)); if (GET_CODE (insn) == CALL_INSN) { @@ -2425,6 +2411,7 @@ record_last_mem_set_info (insn) need to insert a pair of items, as canon_list_insert does. */ canon_modify_mem_list[BLOCK_NUM (insn)] = alloc_INSN_LIST (insn, canon_modify_mem_list[BLOCK_NUM (insn)]); + bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn)); } else note_stores (PATTERN (insn), canon_list_insert, (void*)insn ); @@ -2482,16 +2469,7 @@ compute_hash_table (set_p) sbitmap_vector_zero (reg_set_in_block, n_basic_blocks); /* re-Cache any INSN_LIST nodes we have allocated. */ - { - int i; - for (i = 0; i < n_basic_blocks; i++) - { - if (modify_mem_list[i]) - free_INSN_LIST_list (modify_mem_list + i); - if (canon_modify_mem_list[i]) - free_INSN_LIST_list (canon_modify_mem_list + i); - } - } + clear_modify_mem_tables (); /* Some working arrays used to track first and last set in each block. */ reg_avail_info = (struct reg_avail_info*) gmalloc (max_gcse_regno * sizeof (struct reg_avail_info)); @@ -2712,6 +2690,35 @@ next_set (regno, expr) return expr; } +/* Clear canon_modify_mem_list and modify_mem_list tables. */ +static void +clear_modify_mem_tables () +{ + int i; + + EXECUTE_IF_SET_IN_BITMAP + (canon_modify_mem_list_set, 0, i, + free_INSN_LIST_list (modify_mem_list + i)); + bitmap_clear (canon_modify_mem_list_set); + + EXECUTE_IF_SET_IN_BITMAP + (canon_modify_mem_list_set, 0, i, + free_INSN_LIST_list (canon_modify_mem_list + i)); + bitmap_clear (modify_mem_list_set); +} + +/* Release memory used by modify_mem_list_set and canon_modify_mem_list_set. */ + +static void +free_modify_mem_tables () +{ + clear_modify_mem_tables (); + free (modify_mem_list); + free (canon_modify_mem_list); + modify_mem_list = 0; + canon_modify_mem_list = 0; +} + /* Reset tables used to keep track of what's still available [since the start of the block]. */ @@ -2720,23 +2727,12 @@ reset_opr_set_tables () { /* Maintain a bitmap of which regs have been set since beginning of the block. */ - sbitmap_zero (reg_set_bitmap); + CLEAR_REG_SET (reg_set_bitmap); /* Also keep a record of the last instruction to modify memory. For now this is very trivial, we only record whether any memory location has been modified. */ - { - int i; - - /* re-Cache any INSN_LIST nodes we have allocated. */ - for (i = 0; i < n_basic_blocks; i++) - { - if (modify_mem_list[i]) - free_INSN_LIST_list (modify_mem_list + i); - if (canon_modify_mem_list[i]) - free_INSN_LIST_list (canon_modify_mem_list + i); - } - } + clear_modify_mem_tables (); } /* Return non-zero if the operands of X are not set before INSN in @@ -2775,7 +2771,7 @@ oprs_not_set_p (x, insn) return oprs_not_set_p (XEXP (x, 0), insn); case REG: - return ! TEST_BIT (reg_set_bitmap, REGNO (x)); + return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x)); default: break; @@ -2828,7 +2824,7 @@ mark_set (pat, insn) dest = XEXP (dest, 0); if (GET_CODE (dest) == REG) - SET_BIT (reg_set_bitmap, REGNO (dest)); + SET_REGNO_REG_SET (reg_set_bitmap, REGNO (dest)); else if (GET_CODE (dest) == MEM) record_last_mem_set_info (insn); @@ -2848,7 +2844,7 @@ mark_clobber (pat, insn) clob = XEXP (clob, 0); if (GET_CODE (clob) == REG) - SET_BIT (reg_set_bitmap, REGNO (clob)); + SET_REGNO_REG_SET (reg_set_bitmap, REGNO (clob)); else record_last_mem_set_info (insn); } diff --git a/gcc/lcm.c b/gcc/lcm.c index 4f5d6927161..88e58410d81 100644 --- a/gcc/lcm.c +++ b/gcc/lcm.c @@ -1029,6 +1029,7 @@ optimize_mode_switching (file) int i, j; int n_entities; int max_num_modes = 0; + bool emited = false; #ifdef NORMAL_MODE /* Increment n_basic_blocks before allocating bb_info. */ @@ -1239,10 +1240,16 @@ optimize_mode_switching (file) mode_set = gen_sequence (); end_sequence (); + /* Do not bother to insert empty sequence. */ + if (GET_CODE (mode_set) == SEQUENCE + && !XVECLEN (mode_set, 0)) + continue; + /* If this is an abnormal edge, we'll insert at the end of the previous block. */ if (eg->flags & EDGE_ABNORMAL) { + emited = true; if (GET_CODE (src_bb->end) == JUMP_INSN) emit_insn_before (mode_set, src_bb->end); /* It doesn't make sense to switch to normal mode @@ -1313,10 +1320,16 @@ optimize_mode_switching (file) mode_set = gen_sequence (); end_sequence (); + /* Do not bother to insert empty sequence. */ + if (GET_CODE (mode_set) == SEQUENCE + && !XVECLEN (mode_set, 0)) + continue; + /* If this is an abnormal edge, we'll insert at the end of the previous block. */ if (eg->flags & EDGE_ABNORMAL) { + emited = true; if (GET_CODE (eg->src->end) == JUMP_INSN) emit_insn_before (mode_set, eg->src->end); else if (GET_CODE (eg->src->end) == INSN) @@ -1349,6 +1362,12 @@ optimize_mode_switching (file) mode_set = gen_sequence (); end_sequence (); + /* Do not bother to insert empty sequence. */ + if (GET_CODE (mode_set) == SEQUENCE + && !XVECLEN (mode_set, 0)) + continue; + + emited = true; if (GET_CODE (ptr->insn_ptr) == NOTE && (NOTE_LINE_NUMBER (ptr->insn_ptr) == NOTE_INSN_BASIC_BLOCK)) @@ -1376,6 +1395,9 @@ optimize_mode_switching (file) if (need_commit) commit_edge_insertions (); + if (!need_commit && !emited) + return 0; + /* Ideally we'd figure out what blocks were affected and start from there, but this is enormously complicated by commit_edge_insertions, which would screw up any indicies we'd collected, and also need to diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 006f063475d..56f47516292 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -442,9 +442,11 @@ reg_to_stack (first, file) /* Ok, floating point instructions exist. If not optimizing, build the CFG and run life analysis. */ if (!optimize) - find_basic_blocks (first, max_reg_num (), file); - count_or_remove_death_notes (NULL, 1); - life_analysis (first, file, PROP_DEATH_NOTES); + { + find_basic_blocks (first, max_reg_num (), file); + count_or_remove_death_notes (NULL, 1); + life_analysis (first, file, PROP_DEATH_NOTES); + } mark_dfs_back_edges (); /* Set up block info for each basic block. */ diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index 3cd89e913ea..c443cd7c4f0 100644 --- a/gcc/sched-rgn.c +++ b/gcc/sched-rgn.c @@ -62,6 +62,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "recog.h" #include "sched-int.h" +/* Define when we want to do count REG_DEAD notes before and after scheduling + for sanity checking. We can't do that when conditional execution is used, + as REG_DEAD exist only for unconditional deaths. */ + +#if !defined (HAVE_conditional_execution) && defined (ENABLE_CHECKING) +#define CHECK_DEAD_NOTES 1 +#else +#define CHECK_DEAD_NOTES 0 +#endif + + #ifdef INSN_SCHEDULING /* Some accessor macros for h_i_d members only used within this file. */ #define INSN_REF_COUNT(INSN) (h_i_d[INSN_UID (INSN)].ref_count) @@ -2790,8 +2801,6 @@ init_regions () block_to_bb = (int *) xmalloc ((n_basic_blocks) * sizeof (int)); containing_rgn = (int *) xmalloc ((n_basic_blocks) * sizeof (int)); - blocks = sbitmap_alloc (n_basic_blocks); - /* Compute regions for scheduling. */ if (reload_completed || n_basic_blocks == 1 @@ -2849,21 +2858,26 @@ init_regions () } } - deaths_in_region = (int *) xmalloc (sizeof (int) * nr_regions); - /* Remove all death notes from the subroutine. */ - for (rgn = 0; rgn < nr_regions; rgn++) + if (CHECK_DEAD_NOTES) { - int b; + blocks = sbitmap_alloc (n_basic_blocks); + deaths_in_region = (int *) xmalloc (sizeof (int) * nr_regions); + /* Remove all death notes from the subroutine. */ + for (rgn = 0; rgn < nr_regions; rgn++) + { + int b; - sbitmap_zero (blocks); - for (b = RGN_NR_BLOCKS (rgn) - 1; b >= 0; --b) - SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn) + b]); + sbitmap_zero (blocks); + for (b = RGN_NR_BLOCKS (rgn) - 1; b >= 0; --b) + SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn) + b]); - deaths_in_region[rgn] = count_or_remove_death_notes (blocks, 1); + deaths_in_region[rgn] = count_or_remove_death_notes (blocks, 1); + } + sbitmap_free (blocks); } - - sbitmap_free (blocks); + else + count_or_remove_death_notes (NULL, 1); } /* The one entry point in this file. DUMP_FILE is the dump file for @@ -2916,39 +2930,50 @@ schedule_insns (dump_file) sbitmap_ones (large_region_blocks); blocks = sbitmap_alloc (n_basic_blocks); + sbitmap_zero (blocks); + /* Update life information. For regions consisting of multiple blocks + we've possibly done interblock scheduling that affects global liveness. + For regions consisting of single blocks we need to do only local + liveness. */ for (rgn = 0; rgn < nr_regions; rgn++) if (RGN_NR_BLOCKS (rgn) > 1) any_large_regions = 1; else { - sbitmap_zero (blocks); SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn)]); RESET_BIT (large_region_blocks, rgn_bb_table[RGN_BLOCKS (rgn)]); - - /* Don't update reg info after reload, since that affects - regs_ever_live, which should not change after reload. */ - update_life_info (blocks, UPDATE_LIFE_LOCAL, - (reload_completed ? PROP_DEATH_NOTES - : PROP_DEATH_NOTES | PROP_REG_INFO)); - -#ifndef HAVE_conditional_execution - /* ??? REG_DEAD notes only exist for unconditional deaths. We need - a count of the conditional plus unconditional deaths for this to - work out. */ - /* In the single block case, the count of registers that died should - not have changed during the schedule. */ - if (count_or_remove_death_notes (blocks, 0) != deaths_in_region[rgn]) - abort (); -#endif } + /* Don't update reg info after reload, since that affects + regs_ever_live, which should not change after reload. */ + update_life_info (blocks, UPDATE_LIFE_LOCAL, + (reload_completed ? PROP_DEATH_NOTES + : PROP_DEATH_NOTES | PROP_REG_INFO)); if (any_large_regions) { update_life_info (large_region_blocks, UPDATE_LIFE_GLOBAL, PROP_DEATH_NOTES | PROP_REG_INFO); } + if (CHECK_DEAD_NOTES) + { + /* Remove all death notes from the subroutine. */ + for (rgn = 0; rgn < nr_regions; rgn++) + if (RGN_NR_BLOCKS (rgn) == 1) + { + int b; + + sbitmap_zero (blocks); + SET_BIT (blocks, rgn_bb_table[RGN_BLOCKS (rgn)]); + + if (deaths_in_region[rgn] + != count_or_remove_death_notes (blocks, 0)) + abort (); + } + free (deaths_in_region); + } + /* Reposition the prologue and epilogue notes in case we moved the prologue/epilogue insns. */ if (reload_completed) @@ -3001,7 +3026,5 @@ schedule_insns (dump_file) sbitmap_free (blocks); sbitmap_free (large_region_blocks); - - free (deaths_in_region); } #endif -- cgit v1.2.1