Commit 73991d6a by Jan Hubicka Committed by Jan Hubicka

lcm.c (optimize_mode_switching): Do not rebuild liveness information when no changes has been made.

	* 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.

From-SVN: r46634
parent 415c055a
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.
......
......@@ -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)
{
......
......@@ -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};
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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. */
......
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment