summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-10-30 11:13:49 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-10-30 11:13:49 +0000
commit7fb47f9f1adf513b1b2b5798de845536228fe16d (patch)
tree5aed4d117e8130cabea4a775fc620383c6f0edc9
parent8c2b78bf912345e40f7b955ed80add8d6c49c4dc (diff)
downloadppe42-gcc-7fb47f9f1adf513b1b2b5798de845536228fe16d.tar.gz
ppe42-gcc-7fb47f9f1adf513b1b2b5798de845536228fe16d.zip
* 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
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/df.c17
-rw-r--r--gcc/df.h1
-rw-r--r--gcc/gcse.c106
-rw-r--r--gcc/lcm.c22
-rw-r--r--gcc/reg-stack.c8
-rw-r--r--gcc/sched-rgn.c85
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 <jh@suse.cz>
+
+ * 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 <jh@suse.cz>
* 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
OpenPOWER on IntegriCloud