Commit 23249ac4 by Daniel Berlin Committed by Kenneth Zadeck

re PR rtl-optimization/26855 (ICE in add_deps_for_def with -fmodulo-sched -maltivec)

2006-05-19  Daniel Berlin  <dberlin@dberlin.org>
            Kenneth Zadeck <zadeck@naturalbridge.com>

	PR rtl-optimization/26855

	* df-scan.c (mw_reg_pool, mw_link_pool): New allocation pools for
	multiword refs.
	(df_scan_alloc): Added code to properly handle multiword hard
	registers and add all_blocks parameter.
	(df_scan_free_internal, df_insn_refs_delete, df_ref_record): Added
	code to properly handle multiword hard registers.
	(df_rescan_blocks): Added code to remove deleted blocks from
	bitmap.
	(df_ref_create_structure, df_ref_record): Added code to properly
	handle subregs.
	(df_ref_record_1): Changed DF_REF_CLOBBER into DF_REF_MUST_CLOBBER
	and set DF_REF_PARTIAL.
	(df_defs_record): Changed DF_REF_CLOBBER into DF_REF_MUST_CLOBBER.
	(df_uses_record): Added DF_REF_PARTIAL for subreg. 
	(df_scan_add_problem): Added flags parameter.
	(df_ref_create_structure): Changed switching structure.
	(df_bb_refs_record): Fixed case where duplicate artificial refs
	were created.  Changed location of flags.
	(df_record_entry_block_defs): Added code to make stack pointer
	live in entry block.  Refined cases where frame pointer is needed.
	Changed location of flags.
	(df_record_exit_block_uses, df_insn_refs_record): Changed location of flags.
	(df_set_state): Removed function.
	(df_grow_reg_info, df_reg_chain_unlink, df_ref_remove,
	df_insn_create_insn_record, df_insn_refs_delete, 
	df_ref_create_structure): Formatting changes.  
	* df-core.c (df_mvs_dump, df_set_flags, df_clear_flags,
	df_delete_basic_block): New function.
	(df_init): Changed location of flags.
	(df_add_problem): Added flags parameter and the way flags are
	processed.
	(df_insn_uid_debug, df_ref_debug, debug_df_defno, debug_df_ref,
	debug_df_chain): Improved debugging output.
	(df_insn_debug, df_insn_uid_debug): Added multiword reg support.
	(df_refs_chain_dump): Removed df parameter.
	(df_iterative_dataflow): Added consistency check.
	(df_prune_to_subcfg): Made public.
	(df_analyze_problem): Added blocks_to_init parameter and made
	public.
	(df_ref_record, df_bb_refs_record, df_mark_reg, 
	 df_record_exit_block_uses): Whitespace changes.
	(df_dump): Whitespace changes.
	* df.h: Some reordering to remove forward references.
	(df_ref_flags.DF_REF_MW_HARDREG, DF_REF_PARTIAL,
	DF_REF_MUST_CLOBBER, DF_REF_MAY_CLOBBER): New fields.
	(df_ref_flags.DF_REF_CLOBBER): Deleted field.
	(dataflow.flags): New field.
	(df.flag): Deleted field.
	(df_alloc_function): Added additional bitmap parameter.
	(df_dependent_problem_function): New type.
	(df_problem.changeable_flags): New field.
	(df_ref_flags.DF_REF_DIES_AFTER_THIS_USE, DF_SCAN_INITIAL,
	DF_SCAN_GLOBAL, DF_SCAN_POST_ALLOC, df_state): Removed.
	(df_mw_hardreg): New struct.
	(DF_INSN_UID_MWS): New macro.
	(df_refs_chain_dump, df_ref_debug, df_chain_dump): Removed df
	parameter.
	(df_add_problem, df_ru_add_problem, df_rd_add_problem,
	df_lr_add_problem, df_ur_add_problem, df_urec_add_problem,
	df_ri_add_problem, df_scan_add_problem): Added flags parameter.
	(df_set_state): Removed function.
	(df_set_flags, df_clear_flags, df_delete_basic_block) New functions.
	* df-problems.c (df_chain_dump): Removed df parameter.
	(df_ru_alloc, df_rd_alloc, df_lr_alloc, df_ur_alloc,
	df_urec_alloc, df_chain_alloc, df_ri_alloc): Added all blocks
	parameter.
	(df_ru_alloc, df_rd_alloc): Now resets all blocks.
	(df_rd_bb_local_compute_process_def, df_ur_bb_local_compute,
	df_chain_create_bb, df_create_unused_note, df_ri_bb_compute):
	Split DF_REF_CLOBBER into DF_REF_MAY_CLOBBER and
	DF_REF_MUST_CLOBBER cases.
	(df_ru_bb_local_compute_process_def,
	df_rd_bb_local_compute_process_def, df_lr_bb_local_compute,
	df_lr_bb_local_compute, df_ur_bb_local_compute,
	df_chain_create_bb): Made subreg aware.
	(df_ru_bb_local_compute, df_rd_bb_local_compute,
	df_lr_bb_local_compute, df_lr_bb_local_compute,
	df_chain_create_bb): Cleanup to use proper macros.
	(df_ur_local_finalize, df_urec_local_finalize): Removed unnecessary
	code to fixup bitvectors.
	(df_ri_alloc): Cleared lifetime.
	(df_ignore_stack_reg, df_kill_notes, df_set_notes_for_mw,
	df_create_unused_note): New function.
	(df_ri_bb_compute, df_ri_compute): Added code to create/update
	REG_DEAD and REG_UNUSED notes as well as register information.
	(df_ru_dump, df_rd_dump, df_lr_dump, df_ur_dump, df_urec_dump,
	df_chains_dump): Fixed crash if problem was never run.
	(df_ru_add_problem, df_rd_add_problem, df_lr_add_problem,
	df_ur_add_problem, df_urec_add_problem, df_chain_add_problem,
	df_ri_add_problem): Processes flags in uniform manner.
	(df_ru_alloc, df_ru_local_compute, df_ru_confluence_n, df_ru_free,
	df_ru_dump, df_rd_local_compute, df_rd_confluence_n, df_rd_free,
	df_rd_dump, df_urec_free_bb_info): Formatting changes.
	(df_ru_free_bb_info, df_ru_bb_local_compute, df_ru_dump,
	df_rd_free_bb_info, df_rd_bb_local_compute_process_def,
	df_rd_bb_local_compute, df_rd_dump, df_lr_free_bb_info,
	df_lr_bb_local_compute, df_lr_local_compute, df_ur_free_bb_info,
	df_ur_dump, df_urec_free_bb_info, df_urec_dump,
	df_chain_create_bb, df_ri_bb_compute): Whitespace changes.
	* modulo-sched.c (sms_schedule): Added flag parameter to calls.
	* see.c (see_initialize_data): Ditto.
	* final.c (rest_of_clean_state) Added regstack_completed.
	* rtl.h (regstack_completed): Ditto.
	* reg-stack.c (regstack_completed): Ditto.

From-SVN: r113915
parent d593cb3d
...@@ -45,7 +45,7 @@ Here is an example of using the dataflow routines. ...@@ -45,7 +45,7 @@ Here is an example of using the dataflow routines.
df = df_init (init_flags); df = df_init (init_flags);
df_add_problem (df, problem); df_add_problem (df, problem, flags);
df_set_blocks (df, blocks); df_set_blocks (df, blocks);
...@@ -63,21 +63,20 @@ DF_INIT simply creates a poor man's object (df) that needs to be ...@@ -63,21 +63,20 @@ DF_INIT simply creates a poor man's object (df) that needs to be
passed to all the dataflow routines. df_finish destroys this object passed to all the dataflow routines. df_finish destroys this object
and frees up any allocated memory. and frees up any allocated memory.
There are two flags that can be passed to df_init: There are three flags that can be passed to df_init, each of these
flags controls the scanning of the rtl:
DF_NO_SCAN means that no scanning of the rtl code is performed. This
is used if the problem instance is to do it's own scanning.
DF_HARD_REGS means that the scanning is to build information about DF_HARD_REGS means that the scanning is to build information about
both pseudo registers and hardware registers. Without this both pseudo registers and hardware registers. Without this
information, the problems will be solved only on pseudo registers. information, the problems will be solved only on pseudo registers.
DF_EQUIV_NOTES marks the uses present in EQUIV/EQUAL notes.
DF_SUBREGS return subregs rather than the inner reg.
DF_ADD_PROBLEM adds a problem, defined by an instance to struct DF_ADD_PROBLEM adds a problem, defined by an instance to struct
df_problem, to the set of problems solved in this instance of df. All df_problem, to the set of problems solved in this instance of df. All
calls to add a problem for a given instance of df must occur before calls to add a problem for a given instance of df must occur before
the first call to DF_RESCAN_BLOCKS or DF_ANALYZE. the first call to DF_RESCAN_BLOCKS, DF_SET_BLOCKS or DF_ANALYZE.
For all of the problems defined in df-problems.c, there are For all of the problems defined in df-problems.c, there are
convenience functions named DF_*_ADD_PROBLEM. convenience functions named DF_*_ADD_PROBLEM.
...@@ -297,7 +296,7 @@ are write-only operations. ...@@ -297,7 +296,7 @@ are write-only operations.
static struct df *ddf = NULL; static struct df *ddf = NULL;
struct df *shared_df = NULL; struct df *shared_df = NULL;
static void * df_get_bb_info (struct dataflow *, unsigned int); static void *df_get_bb_info (struct dataflow *, unsigned int);
static void df_set_bb_info (struct dataflow *, unsigned int, void *); static void df_set_bb_info (struct dataflow *, unsigned int, void *);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
Functions to create, destroy and manipulate an instance of df. Functions to create, destroy and manipulate an instance of df.
...@@ -311,14 +310,13 @@ struct df * ...@@ -311,14 +310,13 @@ struct df *
df_init (int flags) df_init (int flags)
{ {
struct df *df = XCNEW (struct df); struct df *df = XCNEW (struct df);
df->flags = flags;
/* This is executed once per compilation to initialize platform /* This is executed once per compilation to initialize platform
specific data structures. */ specific data structures. */
df_hard_reg_init (); df_hard_reg_init ();
/* All df instance must define the scanning problem. */ /* All df instance must define the scanning problem. */
df_scan_add_problem (df); df_scan_add_problem (df, flags);
ddf = df; ddf = df;
return df; return df;
} }
...@@ -326,13 +324,13 @@ df_init (int flags) ...@@ -326,13 +324,13 @@ df_init (int flags)
/* Add PROBLEM to the DF instance. */ /* Add PROBLEM to the DF instance. */
struct dataflow * struct dataflow *
df_add_problem (struct df *df, struct df_problem *problem) df_add_problem (struct df *df, struct df_problem *problem, int flags)
{ {
struct dataflow *dflow; struct dataflow *dflow;
/* First try to add the dependent problem. */ /* First try to add the dependent problem. */
if (problem->dependent_problem) if (problem->dependent_problem_fun)
df_add_problem (df, problem->dependent_problem); (problem->dependent_problem_fun) (df, 0);
/* Check to see if this problem has already been defined. If it /* Check to see if this problem has already been defined. If it
has, just return that instance, if not, add it to the end of the has, just return that instance, if not, add it to the end of the
...@@ -343,6 +341,7 @@ df_add_problem (struct df *df, struct df_problem *problem) ...@@ -343,6 +341,7 @@ df_add_problem (struct df *df, struct df_problem *problem)
/* Make a new one and add it to the end. */ /* Make a new one and add it to the end. */
dflow = XCNEW (struct dataflow); dflow = XCNEW (struct dataflow);
dflow->flags = flags;
dflow->df = df; dflow->df = df;
dflow->problem = problem; dflow->problem = problem;
df->problems_in_order[df->num_problems_defined++] = dflow; df->problems_in_order[df->num_problems_defined++] = dflow;
...@@ -352,6 +351,36 @@ df_add_problem (struct df *df, struct df_problem *problem) ...@@ -352,6 +351,36 @@ df_add_problem (struct df *df, struct df_problem *problem)
} }
/* Set the MASK flags in the DFLOW problem. The old flags are
returned. If a flag is not allowed to be changed this will fail if
checking is enabled. */
int
df_set_flags (struct dataflow *dflow, int mask)
{
int old_flags = dflow->flags;
gcc_assert (!(mask & (~dflow->problem->changeable_flags)));
dflow->flags |= mask;
return old_flags;
}
/* Clear the MASK flags in the DFLOW problem. The old flags are
returned. If a flag is not allowed to be changed this will fail if
checking is enabled. */
int
df_clear_flags (struct dataflow *dflow, int mask)
{
int old_flags = dflow->flags;
gcc_assert (!(mask & (~dflow->problem->changeable_flags)));
dflow->flags &= !mask;
return old_flags;
}
/* Set the blocks that are to be considered for analysis. If this is /* Set the blocks that are to be considered for analysis. If this is
not called or is called with null, the entire function in not called or is called with null, the entire function in
analyzed. */ analyzed. */
...@@ -435,6 +464,26 @@ df_set_blocks (struct df *df, bitmap blocks) ...@@ -435,6 +464,26 @@ df_set_blocks (struct df *df, bitmap blocks)
} }
/* Free all of the per basic block dataflow from all of the problems.
This is typically called before a basic block is deleted and the
problem will be reanalyzed. */
void
df_delete_basic_block (struct df *df, int bb_index)
{
basic_block bb = BASIC_BLOCK (bb_index);
int i;
for (i = 0; i < df->num_problems_defined; i++)
{
struct dataflow *dflow = df->problems_in_order[i];
if (dflow->problem->free_bb_fun)
dflow->problem->free_bb_fun
(dflow, bb, df_get_bb_info (dflow, bb_index));
}
}
/* Free all the dataflow info and the DF structure. This should be /* Free all the dataflow info and the DF structure. This should be
called from the df_finish macro which also NULLs the parm. */ called from the df_finish macro which also NULLs the parm. */
...@@ -594,6 +643,8 @@ df_iterative_dataflow (struct dataflow *dataflow, ...@@ -594,6 +643,8 @@ df_iterative_dataflow (struct dataflow *dataflow,
sbitmap_zero (pending); sbitmap_zero (pending);
sbitmap_zero (considered); sbitmap_zero (considered);
gcc_assert (dataflow->problem->dir);
EXECUTE_IF_SET_IN_BITMAP (blocks_to_consider, 0, idx, bi) EXECUTE_IF_SET_IN_BITMAP (blocks_to_consider, 0, idx, bi)
{ {
SET_BIT (considered, idx); SET_BIT (considered, idx);
...@@ -696,7 +747,7 @@ df_prune_to_subcfg (int list[], unsigned len, bitmap blocks) ...@@ -696,7 +747,7 @@ df_prune_to_subcfg (int list[], unsigned len, bitmap blocks)
small fixup fringe sub sub small fixup fringe sub sub
*/ */
static void void
df_analyze_problem (struct dataflow *dflow, df_analyze_problem (struct dataflow *dflow,
bitmap blocks_to_consider, bitmap blocks_to_consider,
bitmap blocks_to_init, bitmap blocks_to_init,
...@@ -705,7 +756,7 @@ df_analyze_problem (struct dataflow *dflow, ...@@ -705,7 +756,7 @@ df_analyze_problem (struct dataflow *dflow,
{ {
/* (Re)Allocate the datastructures necessary to solve the problem. */ /* (Re)Allocate the datastructures necessary to solve the problem. */
if (dflow->problem->alloc_fun) if (dflow->problem->alloc_fun)
dflow->problem->alloc_fun (dflow, blocks_to_scan); dflow->problem->alloc_fun (dflow, blocks_to_scan, blocks_to_init);
/* Set up the problem and compute the local information. This /* Set up the problem and compute the local information. This
function is passed both the blocks_to_consider and the function is passed both the blocks_to_consider and the
...@@ -1066,7 +1117,7 @@ df_dump (struct df *df, FILE *file) ...@@ -1066,7 +1117,7 @@ df_dump (struct df *df, FILE *file)
{ {
int i; int i;
if (! df || ! file) if (!df || !file)
return; return;
fprintf (file, "\n\n%s\n", current_function_name ()); fprintf (file, "\n\n%s\n", current_function_name ());
...@@ -1082,8 +1133,7 @@ df_dump (struct df *df, FILE *file) ...@@ -1082,8 +1133,7 @@ df_dump (struct df *df, FILE *file)
void void
df_refs_chain_dump (struct df *df, struct df_ref *ref, df_refs_chain_dump (struct df_ref *ref, bool follow_chain, FILE *file)
bool follow_chain, FILE *file)
{ {
fprintf (file, "{ "); fprintf (file, "{ ");
while (ref) while (ref)
...@@ -1093,7 +1143,7 @@ df_refs_chain_dump (struct df *df, struct df_ref *ref, ...@@ -1093,7 +1143,7 @@ df_refs_chain_dump (struct df *df, struct df_ref *ref,
DF_REF_ID (ref), DF_REF_ID (ref),
DF_REF_REGNO (ref)); DF_REF_REGNO (ref));
if (follow_chain) if (follow_chain)
df_chain_dump (df, DF_REF_CHAIN (ref), file); df_chain_dump (DF_REF_CHAIN (ref), file);
ref = ref->next_ref; ref = ref->next_ref;
} }
fprintf (file, "}"); fprintf (file, "}");
...@@ -1118,13 +1168,32 @@ df_regs_chain_dump (struct df *df ATTRIBUTE_UNUSED, struct df_ref *ref, FILE *f ...@@ -1118,13 +1168,32 @@ df_regs_chain_dump (struct df *df ATTRIBUTE_UNUSED, struct df_ref *ref, FILE *f
} }
void static void
df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file) df_mws_dump (struct df_mw_hardreg *mws, FILE *file)
{ {
unsigned int uid; while (mws)
int bbi; {
struct df_link *regs = mws->regs;
fprintf (file, "%c%d(",
(mws->type == DF_REF_REG_DEF) ? 'd' : 'u',
DF_REF_REGNO (regs->ref));
while (regs)
{
fprintf (file, "%d ", DF_REF_REGNO (regs->ref));
regs = regs->next;
}
uid = INSN_UID (insn); fprintf (file, ") ");
mws = mws->next;
}
}
static void
df_insn_uid_debug (struct df *df, unsigned int uid,
bool follow_chain, FILE *file)
{
int bbi;
if (DF_INSN_UID_DEFS (df, uid)) if (DF_INSN_UID_DEFS (df, uid))
bbi = DF_REF_BBNO (DF_INSN_UID_DEFS (df, uid)); bbi = DF_REF_BBNO (DF_INSN_UID_DEFS (df, uid));
...@@ -1133,15 +1202,36 @@ df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file) ...@@ -1133,15 +1202,36 @@ df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file)
else else
bbi = -1; bbi = -1;
fprintf (file, "insn %d bb %d luid %d defs ", fprintf (file, "insn %d bb %d luid %d",
uid, bbi, DF_INSN_LUID (df, insn)); uid, bbi, DF_INSN_UID_LUID (df, uid));
df_refs_chain_dump (df, DF_INSN_UID_DEFS (df, uid), follow_chain, file); if (DF_INSN_UID_DEFS (df, uid))
fprintf (file, " defs "); {
df_refs_chain_dump (df, DF_INSN_UID_USES (df, uid), follow_chain, file); fprintf (file, " defs ");
df_refs_chain_dump (DF_INSN_UID_DEFS (df, uid), follow_chain, file);
}
if (DF_INSN_UID_USES (df, uid))
{
fprintf (file, " uses ");
df_refs_chain_dump (DF_INSN_UID_USES (df, uid), follow_chain, file);
}
if (DF_INSN_UID_MWS (df, uid))
{
fprintf (file, " mws ");
df_mws_dump (DF_INSN_UID_MWS (df, uid), file);
}
fprintf (file, "\n"); fprintf (file, "\n");
} }
void
df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file)
{
df_insn_uid_debug (df, INSN_UID (insn), follow_chain, file);
}
void void
df_insn_debug_regno (struct df *df, rtx insn, FILE *file) df_insn_debug_regno (struct df *df, rtx insn, FILE *file)
{ {
...@@ -1177,17 +1267,17 @@ df_regno_debug (struct df *df, unsigned int regno, FILE *file) ...@@ -1177,17 +1267,17 @@ df_regno_debug (struct df *df, unsigned int regno, FILE *file)
void void
df_ref_debug (struct df *df, struct df_ref *ref, FILE *file) df_ref_debug (struct df_ref *ref, FILE *file)
{ {
fprintf (file, "%c%d ", fprintf (file, "%c%d ",
DF_REF_REG_DEF_P (ref) ? 'd' : 'u', DF_REF_REG_DEF_P (ref) ? 'd' : 'u',
DF_REF_ID (ref)); DF_REF_ID (ref));
fprintf (file, "reg %d bb %d luid %d insn %d chain ", fprintf (file, "reg %d bb %d insn %d flag %x chain ",
DF_REF_REGNO (ref), DF_REF_REGNO (ref),
DF_REF_BBNO (ref), DF_REF_BBNO (ref),
DF_REF_INSN (ref) ? DF_INSN_LUID (df, DF_REF_INSN (ref)) : -1, DF_REF_INSN (ref) ? INSN_UID (DF_REF_INSN (ref)) : -1,
DF_REF_INSN (ref) ? INSN_UID (DF_REF_INSN (ref)) : -1); DF_REF_FLAGS (ref));
df_chain_dump (df, DF_REF_CHAIN (ref), file); df_chain_dump (DF_REF_CHAIN (ref), file);
fprintf (file, "\n"); fprintf (file, "\n");
} }
...@@ -1218,27 +1308,27 @@ debug_df_regno (unsigned int regno) ...@@ -1218,27 +1308,27 @@ debug_df_regno (unsigned int regno)
void void
debug_df_ref (struct df_ref *ref) debug_df_ref (struct df_ref *ref)
{ {
df_ref_debug (ddf, ref, stderr); df_ref_debug (ref, stderr);
} }
void void
debug_df_defno (unsigned int defno) debug_df_defno (unsigned int defno)
{ {
df_ref_debug (ddf, DF_DEFS_GET (ddf, defno), stderr); df_ref_debug (DF_DEFS_GET (ddf, defno), stderr);
} }
void void
debug_df_useno (unsigned int defno) debug_df_useno (unsigned int defno)
{ {
df_ref_debug (ddf, DF_USES_GET (ddf, defno), stderr); df_ref_debug (DF_USES_GET (ddf, defno), stderr);
} }
void void
debug_df_chain (struct df_link *link) debug_df_chain (struct df_link *link)
{ {
df_chain_dump (ddf, link, stderr); df_chain_dump (link, stderr);
fputc ('\n', stderr); fputc ('\n', stderr);
} }
...@@ -43,30 +43,23 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -43,30 +43,23 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "timevar.h" #include "timevar.h"
#include "df.h" #include "df.h"
#include "vecprim.h" #include "vecprim.h"
#include "except.h"
#if 0
#define REG_DEAD_DEBUGGING
#endif
#define DF_SPARSE_THRESHOLD 32 #define DF_SPARSE_THRESHOLD 32
static bitmap seen_in_block = NULL; static bitmap seen_in_block = NULL;
static bitmap seen_in_insn = NULL; static bitmap seen_in_insn = NULL;
static void df_ri_dump (struct dataflow *, FILE *);
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
Public functions access functions for the dataflow problems. Public functions access functions for the dataflow problems.
----------------------------------------------------------------------------*/ ----------------------------------------------------------------------------*/
/* Get the instance of the problem that DFLOW is dependent on. */
struct dataflow *
df_get_dependent_problem (struct dataflow *dflow)
{
struct df *df = dflow->df;
struct df_problem *dependent_problem = dflow->problem->dependent_problem;
gcc_assert (dependent_problem);
return df->problems_by_index[dependent_problem->id];
}
/* Create a du or ud chain from SRC to DST and link it into SRC. */ /* Create a du or ud chain from SRC to DST and link it into SRC. */
struct df_link * struct df_link *
...@@ -207,7 +200,7 @@ df_grow_bb_info (struct dataflow *dflow) ...@@ -207,7 +200,7 @@ df_grow_bb_info (struct dataflow *dflow)
/* Dump a def-use or use-def chain for REF to FILE. */ /* Dump a def-use or use-def chain for REF to FILE. */
void void
df_chain_dump (struct df *df ATTRIBUTE_UNUSED, struct df_link *link, FILE *file) df_chain_dump (struct df_link *link, FILE *file)
{ {
fprintf (file, "{ "); fprintf (file, "{ ");
for (; link; link = link->next) for (; link; link = link->next)
...@@ -346,21 +339,23 @@ df_ru_free_bb_info (struct dataflow *dflow, ...@@ -346,21 +339,23 @@ df_ru_free_bb_info (struct dataflow *dflow,
not touched unless the block is new. */ not touched unless the block is new. */
static void static void
df_ru_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_ru_alloc (struct dataflow *dflow,
bitmap blocks_to_rescan ATTRIBUTE_UNUSED,
bitmap all_blocks)
{ {
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
unsigned int reg_size = max_reg_num (); unsigned int reg_size = max_reg_num ();
if (! dflow->block_pool) if (!dflow->block_pool)
dflow->block_pool = create_alloc_pool ("df_ru_block pool", dflow->block_pool = create_alloc_pool ("df_ru_block pool",
sizeof (struct df_ru_bb_info), 50); sizeof (struct df_ru_bb_info), 50);
if (dflow->problem_data) if (dflow->problem_data)
{ {
unsigned int i; unsigned int i;
struct df_ru_problem_data *problem_data = struct df_ru_problem_data *problem_data
(struct df_ru_problem_data *) dflow->problem_data; = (struct df_ru_problem_data *) dflow->problem_data;
for (i = 0; i < problem_data->use_sites_size; i++) for (i = 0; i < problem_data->use_sites_size; i++)
{ {
...@@ -401,7 +396,7 @@ df_ru_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) ...@@ -401,7 +396,7 @@ df_ru_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
we have to process all of the blocks before doing the we have to process all of the blocks before doing the
analysis. */ analysis. */
EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
{ {
struct df_ru_bb_info *bb_info = df_ru_get_bb_info (dflow, bb_index); struct df_ru_bb_info *bb_info = df_ru_get_bb_info (dflow, bb_index);
if (bb_info) if (bb_info)
...@@ -435,7 +430,10 @@ df_ru_bb_local_compute_process_def (struct dataflow *dflow, ...@@ -435,7 +430,10 @@ df_ru_bb_local_compute_process_def (struct dataflow *dflow,
struct df *df = dflow->df; struct df *df = dflow->df;
while (def) while (def)
{ {
if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP)) if ((top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
/* If the def is to only part of the reg, it is as if it did
not happen, since some of the bits may get thru. */
&& (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)))
{ {
unsigned int regno = DF_REF_REGNO (def); unsigned int regno = DF_REF_REGNO (def);
unsigned int begin = DF_REG_USE_GET (df, regno)->begin; unsigned int begin = DF_REG_USE_GET (df, regno)->begin;
...@@ -453,10 +451,10 @@ df_ru_bb_local_compute_process_def (struct dataflow *dflow, ...@@ -453,10 +451,10 @@ df_ru_bb_local_compute_process_def (struct dataflow *dflow,
} }
else else
{ {
struct df_ru_problem_data * problem_data = struct df_ru_problem_data * problem_data
(struct df_ru_problem_data *)dflow->problem_data; = (struct df_ru_problem_data *)dflow->problem_data;
bitmap uses = bitmap uses
df_ref_bitmap (problem_data->use_sites, regno, = df_ref_bitmap (problem_data->use_sites, regno,
begin, n_uses); begin, n_uses);
bitmap_ior_into (bb_info->kill, uses); bitmap_ior_into (bb_info->kill, uses);
bitmap_and_compl_into (bb_info->gen, uses); bitmap_and_compl_into (bb_info->gen, uses);
...@@ -519,18 +517,18 @@ df_ru_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) ...@@ -519,18 +517,18 @@ df_ru_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
FOR_BB_INSNS (bb, insn) FOR_BB_INSNS (bb, insn)
{ {
unsigned int uid = INSN_UID (insn); unsigned int uid = INSN_UID (insn);
if (! INSN_P (insn)) if (!INSN_P (insn))
continue; continue;
df_ru_bb_local_compute_process_def (dflow, bb_info, df_ru_bb_local_compute_process_def (dflow, bb_info,
DF_INSN_UID_GET (df, uid)->defs, 0); DF_INSN_UID_DEFS (df, uid), 0);
/* The use processing must happen after the defs processing even /* The use processing must happen after the defs processing even
though the uses logically happen first since the defs clear though the uses logically happen first since the defs clear
the gen set. Otherwise, a use for regno occuring in the same the gen set. Otherwise, a use for regno occuring in the same
instruction as a def for regno would be cleared. */ instruction as a def for regno would be cleared. */
df_ru_bb_local_compute_process_use (bb_info, df_ru_bb_local_compute_process_use (bb_info,
DF_INSN_UID_GET (df, uid)->uses, 0); DF_INSN_UID_USES (df, uid), 0);
bitmap_ior_into (seen_in_block, seen_in_insn); bitmap_ior_into (seen_in_block, seen_in_insn);
bitmap_clear (seen_in_insn); bitmap_clear (seen_in_insn);
...@@ -556,8 +554,8 @@ df_ru_local_compute (struct dataflow *dflow, ...@@ -556,8 +554,8 @@ df_ru_local_compute (struct dataflow *dflow,
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
unsigned int regno; unsigned int regno;
struct df_ru_problem_data *problem_data = struct df_ru_problem_data *problem_data
(struct df_ru_problem_data *) dflow->problem_data; = (struct df_ru_problem_data *) dflow->problem_data;
bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call;
bitmap dense_invalidated = problem_data->dense_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call;
...@@ -616,8 +614,8 @@ df_ru_confluence_n (struct dataflow *dflow, edge e) ...@@ -616,8 +614,8 @@ df_ru_confluence_n (struct dataflow *dflow, edge e)
if (e->flags & EDGE_EH) if (e->flags & EDGE_EH)
{ {
struct df_ru_problem_data *problem_data = struct df_ru_problem_data *problem_data
(struct df_ru_problem_data *) dflow->problem_data; = (struct df_ru_problem_data *) dflow->problem_data;
bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call;
bitmap dense_invalidated = problem_data->dense_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call;
struct df *df = dflow->df; struct df *df = dflow->df;
...@@ -691,8 +689,8 @@ static void ...@@ -691,8 +689,8 @@ static void
df_ru_free (struct dataflow *dflow) df_ru_free (struct dataflow *dflow)
{ {
unsigned int i; unsigned int i;
struct df_ru_problem_data *problem_data = struct df_ru_problem_data *problem_data
(struct df_ru_problem_data *) dflow->problem_data; = (struct df_ru_problem_data *) dflow->problem_data;
if (problem_data) if (problem_data)
{ {
...@@ -737,10 +735,13 @@ df_ru_dump (struct dataflow *dflow, FILE *file) ...@@ -737,10 +735,13 @@ df_ru_dump (struct dataflow *dflow, FILE *file)
{ {
basic_block bb; basic_block bb;
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_ru_problem_data *problem_data = struct df_ru_problem_data *problem_data
(struct df_ru_problem_data *) dflow->problem_data; = (struct df_ru_problem_data *) dflow->problem_data;
unsigned int m = max_reg_num (); unsigned int m = max_reg_num ();
unsigned int regno; unsigned int regno;
if (!dflow->block_info)
return;
fprintf (file, "Reaching uses:\n"); fprintf (file, "Reaching uses:\n");
...@@ -761,7 +762,7 @@ df_ru_dump (struct dataflow *dflow, FILE *file) ...@@ -761,7 +762,7 @@ df_ru_dump (struct dataflow *dflow, FILE *file)
struct df_ru_bb_info *bb_info = df_ru_get_bb_info (dflow, bb->index); struct df_ru_bb_info *bb_info = df_ru_get_bb_info (dflow, bb->index);
df_print_bb_index (bb, file); df_print_bb_index (bb, file);
if (! bb_info->in) if (!bb_info->in)
continue; continue;
fprintf (file, " in \t"); fprintf (file, " in \t");
...@@ -793,7 +794,8 @@ static struct df_problem problem_RU = ...@@ -793,7 +794,8 @@ static struct df_problem problem_RU =
NULL, /* Finalize function. */ NULL, /* Finalize function. */
df_ru_free, /* Free all of the problem information. */ df_ru_free, /* Free all of the problem information. */
df_ru_dump, /* Debugging. */ df_ru_dump, /* Debugging. */
NULL /* Dependent problem. */ NULL, /* Dependent problem. */
0 /* Changeable flags. */
}; };
...@@ -803,9 +805,9 @@ static struct df_problem problem_RU = ...@@ -803,9 +805,9 @@ static struct df_problem problem_RU =
solution. */ solution. */
struct dataflow * struct dataflow *
df_ru_add_problem (struct df *df) df_ru_add_problem (struct df *df, int flags)
{ {
return df_add_problem (df, &problem_RU); return df_add_problem (df, &problem_RU, flags);
} }
...@@ -869,21 +871,23 @@ df_rd_free_bb_info (struct dataflow *dflow, ...@@ -869,21 +871,23 @@ df_rd_free_bb_info (struct dataflow *dflow,
not touched unless the block is new. */ not touched unless the block is new. */
static void static void
df_rd_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_rd_alloc (struct dataflow *dflow,
bitmap blocks_to_rescan ATTRIBUTE_UNUSED,
bitmap all_blocks)
{ {
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
unsigned int reg_size = max_reg_num (); unsigned int reg_size = max_reg_num ();
if (! dflow->block_pool) if (!dflow->block_pool)
dflow->block_pool = create_alloc_pool ("df_rd_block pool", dflow->block_pool = create_alloc_pool ("df_rd_block pool",
sizeof (struct df_rd_bb_info), 50); sizeof (struct df_rd_bb_info), 50);
if (dflow->problem_data) if (dflow->problem_data)
{ {
unsigned int i; unsigned int i;
struct df_rd_problem_data *problem_data = struct df_rd_problem_data *problem_data
(struct df_rd_problem_data *) dflow->problem_data; = (struct df_rd_problem_data *) dflow->problem_data;
for (i = 0; i < problem_data->def_sites_size; i++) for (i = 0; i < problem_data->def_sites_size; i++)
{ {
...@@ -920,11 +924,11 @@ df_rd_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) ...@@ -920,11 +924,11 @@ df_rd_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
df_grow_bb_info (dflow); df_grow_bb_info (dflow);
/* Because of the clustering of all def sites for the same pseudo, /* Because of the clustering of all use sites for the same pseudo,
we have to process all of the blocks before doing the we have to process all of the blocks before doing the
analysis. */ analysis. */
EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
{ {
struct df_rd_bb_info *bb_info = df_rd_get_bb_info (dflow, bb_index); struct df_rd_bb_info *bb_info = df_rd_get_bb_info (dflow, bb_index);
if (bb_info) if (bb_info)
...@@ -970,7 +974,11 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow, ...@@ -970,7 +974,11 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow,
{ {
/* The first def for regno in insn gets to knock out the /* The first def for regno in insn gets to knock out the
defs from other instructions. */ defs from other instructions. */
if (!bitmap_bit_p (seen_in_insn, regno)) if ((!bitmap_bit_p (seen_in_insn, regno))
/* If the def is to only part of the reg, it does
not kill the other defs that reach here. */
&& (!((DF_REF_FLAGS (def) & DF_REF_PARTIAL)
|| (DF_REF_FLAGS (def) & DF_REF_MAY_CLOBBER))))
{ {
if (n_defs > DF_SPARSE_THRESHOLD) if (n_defs > DF_SPARSE_THRESHOLD)
{ {
...@@ -979,11 +987,10 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow, ...@@ -979,11 +987,10 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow,
} }
else else
{ {
struct df_rd_problem_data * problem_data = struct df_rd_problem_data * problem_data
(struct df_rd_problem_data *)dflow->problem_data; = (struct df_rd_problem_data *)dflow->problem_data;
bitmap defs = bitmap defs = df_ref_bitmap (problem_data->def_sites,
df_ref_bitmap (problem_data->def_sites, regno, regno, begin, n_defs);
begin, n_defs);
bitmap_ior_into (bb_info->kill, defs); bitmap_ior_into (bb_info->kill, defs);
bitmap_and_compl_into (bb_info->gen, defs); bitmap_and_compl_into (bb_info->gen, defs);
} }
...@@ -992,7 +999,8 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow, ...@@ -992,7 +999,8 @@ df_rd_bb_local_compute_process_def (struct dataflow *dflow,
bitmap_set_bit (seen_in_insn, regno); bitmap_set_bit (seen_in_insn, regno);
/* All defs for regno in the instruction may be put into /* All defs for regno in the instruction may be put into
the gen set. */ the gen set. */
if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER)) if (!(DF_REF_FLAGS (def)
& (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
bitmap_set_bit (bb_info->gen, DF_REF_ID (def)); bitmap_set_bit (bb_info->gen, DF_REF_ID (def));
} }
} }
...@@ -1020,11 +1028,11 @@ df_rd_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) ...@@ -1020,11 +1028,11 @@ df_rd_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
{ {
unsigned int uid = INSN_UID (insn); unsigned int uid = INSN_UID (insn);
if (! INSN_P (insn)) if (!INSN_P (insn))
continue; continue;
df_rd_bb_local_compute_process_def (dflow, bb_info, df_rd_bb_local_compute_process_def (dflow, bb_info,
DF_INSN_UID_GET (df, uid)->defs, 0); DF_INSN_UID_DEFS (df, uid), 0);
/* This complex dance with the two bitmaps is required because /* This complex dance with the two bitmaps is required because
instructions can assign twice to the same pseudo. This instructions can assign twice to the same pseudo. This
...@@ -1056,8 +1064,8 @@ df_rd_local_compute (struct dataflow *dflow, ...@@ -1056,8 +1064,8 @@ df_rd_local_compute (struct dataflow *dflow,
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
unsigned int regno; unsigned int regno;
struct df_rd_problem_data *problem_data = struct df_rd_problem_data *problem_data
(struct df_rd_problem_data *) dflow->problem_data; = (struct df_rd_problem_data *) dflow->problem_data;
bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call;
bitmap dense_invalidated = problem_data->dense_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call;
...@@ -1117,8 +1125,8 @@ df_rd_confluence_n (struct dataflow *dflow, edge e) ...@@ -1117,8 +1125,8 @@ df_rd_confluence_n (struct dataflow *dflow, edge e)
if (e->flags & EDGE_EH) if (e->flags & EDGE_EH)
{ {
struct df_rd_problem_data *problem_data = struct df_rd_problem_data *problem_data
(struct df_rd_problem_data *) dflow->problem_data; = (struct df_rd_problem_data *) dflow->problem_data;
bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call; bitmap sparse_invalidated = problem_data->sparse_invalidated_by_call;
bitmap dense_invalidated = problem_data->dense_invalidated_by_call; bitmap dense_invalidated = problem_data->dense_invalidated_by_call;
struct df *df = dflow->df; struct df *df = dflow->df;
...@@ -1192,8 +1200,8 @@ static void ...@@ -1192,8 +1200,8 @@ static void
df_rd_free (struct dataflow *dflow) df_rd_free (struct dataflow *dflow)
{ {
unsigned int i; unsigned int i;
struct df_rd_problem_data *problem_data = struct df_rd_problem_data *problem_data
(struct df_rd_problem_data *) dflow->problem_data; = (struct df_rd_problem_data *) dflow->problem_data;
if (problem_data) if (problem_data)
{ {
...@@ -1238,11 +1246,14 @@ df_rd_dump (struct dataflow *dflow, FILE *file) ...@@ -1238,11 +1246,14 @@ df_rd_dump (struct dataflow *dflow, FILE *file)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
basic_block bb; basic_block bb;
struct df_rd_problem_data *problem_data = struct df_rd_problem_data *problem_data
(struct df_rd_problem_data *) dflow->problem_data; = (struct df_rd_problem_data *) dflow->problem_data;
unsigned int m = max_reg_num (); unsigned int m = max_reg_num ();
unsigned int regno; unsigned int regno;
if (!dflow->block_info)
return;
fprintf (file, "Reaching defs:\n\n"); fprintf (file, "Reaching defs:\n\n");
fprintf (file, " sparse invalidated \t"); fprintf (file, " sparse invalidated \t");
...@@ -1262,7 +1273,7 @@ df_rd_dump (struct dataflow *dflow, FILE *file) ...@@ -1262,7 +1273,7 @@ df_rd_dump (struct dataflow *dflow, FILE *file)
struct df_rd_bb_info *bb_info = df_rd_get_bb_info (dflow, bb->index); struct df_rd_bb_info *bb_info = df_rd_get_bb_info (dflow, bb->index);
df_print_bb_index (bb, file); df_print_bb_index (bb, file);
if (! bb_info->in) if (!bb_info->in)
continue; continue;
fprintf (file, " in\t(%d)\n", (int) bitmap_count_bits (bb_info->in)); fprintf (file, " in\t(%d)\n", (int) bitmap_count_bits (bb_info->in));
...@@ -1294,7 +1305,8 @@ static struct df_problem problem_RD = ...@@ -1294,7 +1305,8 @@ static struct df_problem problem_RD =
NULL, /* Finalize function. */ NULL, /* Finalize function. */
df_rd_free, /* Free all of the problem information. */ df_rd_free, /* Free all of the problem information. */
df_rd_dump, /* Debugging. */ df_rd_dump, /* Debugging. */
NULL /* Dependent problem. */ NULL, /* Dependent problem. */
0 /* Changeable flags. */
}; };
...@@ -1304,9 +1316,9 @@ static struct df_problem problem_RD = ...@@ -1304,9 +1316,9 @@ static struct df_problem problem_RD =
solution. */ solution. */
struct dataflow * struct dataflow *
df_rd_add_problem (struct df *df) df_rd_add_problem (struct df *df, int flags)
{ {
return df_add_problem (df, &problem_RD); return df_add_problem (df, &problem_RD, flags);
} }
...@@ -1360,21 +1372,18 @@ df_lr_free_bb_info (struct dataflow *dflow, ...@@ -1360,21 +1372,18 @@ df_lr_free_bb_info (struct dataflow *dflow,
not touched unless the block is new. */ not touched unless the block is new. */
static void static void
df_lr_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_lr_alloc (struct dataflow *dflow, bitmap blocks_to_rescan,
bitmap all_blocks ATTRIBUTE_UNUSED)
{ {
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
if (! dflow->block_pool) if (!dflow->block_pool)
dflow->block_pool = create_alloc_pool ("df_lr_block pool", dflow->block_pool = create_alloc_pool ("df_lr_block pool",
sizeof (struct df_lr_bb_info), 50); sizeof (struct df_lr_bb_info), 50);
df_grow_bb_info (dflow); df_grow_bb_info (dflow);
/* Because of the clustering of all def sites for the same pseudo,
we have to process all of the blocks before doing the
analysis. */
EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi)
{ {
struct df_lr_bb_info *bb_info = df_lr_get_bb_info (dflow, bb_index); struct df_lr_bb_info *bb_info = df_lr_get_bb_info (dflow, bb_index);
...@@ -1410,7 +1419,8 @@ df_lr_bb_local_compute (struct dataflow *dflow, ...@@ -1410,7 +1419,8 @@ df_lr_bb_local_compute (struct dataflow *dflow,
/* Process the registers set in an exception handler. */ /* Process the registers set in an exception handler. */
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref) for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0) if (((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
&& (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)))
{ {
unsigned int dregno = DF_REF_REGNO (def); unsigned int dregno = DF_REF_REGNO (def);
bitmap_set_bit (bb_info->def, dregno); bitmap_set_bit (bb_info->def, dregno);
...@@ -1427,12 +1437,12 @@ df_lr_bb_local_compute (struct dataflow *dflow, ...@@ -1427,12 +1437,12 @@ df_lr_bb_local_compute (struct dataflow *dflow,
{ {
unsigned int uid = INSN_UID (insn); unsigned int uid = INSN_UID (insn);
if (! INSN_P (insn)) if (!INSN_P (insn))
continue; continue;
if (CALL_P (insn)) if (CALL_P (insn))
{ {
for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
{ {
unsigned int dregno = DF_REF_REGNO (def); unsigned int dregno = DF_REF_REGNO (def);
...@@ -1443,15 +1453,19 @@ df_lr_bb_local_compute (struct dataflow *dflow, ...@@ -1443,15 +1453,19 @@ df_lr_bb_local_compute (struct dataflow *dflow,
current_function_return_rtx, current_function_return_rtx,
(rtx *)0))) (rtx *)0)))
{ {
/* Add def to set of defs in this BB. */ /* If the def is to only part of the reg, it does
bitmap_set_bit (bb_info->def, dregno); not kill the other defs that reach here. */
bitmap_clear_bit (bb_info->use, dregno); if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
{
bitmap_set_bit (bb_info->def, dregno);
bitmap_clear_bit (bb_info->use, dregno);
}
} }
} }
} }
else else
{ {
for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
{ {
unsigned int dregno = DF_REF_REGNO (def); unsigned int dregno = DF_REF_REGNO (def);
...@@ -1459,25 +1473,30 @@ df_lr_bb_local_compute (struct dataflow *dflow, ...@@ -1459,25 +1473,30 @@ df_lr_bb_local_compute (struct dataflow *dflow,
&& dregno < FIRST_PSEUDO_REGISTER) && dregno < FIRST_PSEUDO_REGISTER)
{ {
unsigned int i; unsigned int i;
unsigned int end = unsigned int end = dregno
dregno + hard_regno_nregs[dregno][GET_MODE (DF_REF_REG (def))] - 1; + hard_regno_nregs[dregno][GET_MODE (DF_REF_REG (def))] - 1;
for (i = dregno; i <= end; ++i) for (i = dregno; i <= end; ++i)
regs_asm_clobbered[i] = 1; regs_asm_clobbered[i] = 1;
} }
/* Add def to set of defs in this BB. */ /* If the def is to only part of the reg, it does
bitmap_set_bit (bb_info->def, dregno); not kill the other defs that reach here. */
bitmap_clear_bit (bb_info->use, dregno); if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
{
bitmap_set_bit (bb_info->def, dregno);
bitmap_clear_bit (bb_info->use, dregno);
}
} }
} }
for (use = DF_INSN_UID_GET (df, uid)->uses; use; use = use->next_ref) for (use = DF_INSN_UID_USES (df, uid); use; use = use->next_ref)
/* Add use to set of uses in this BB. */ /* Add use to set of uses in this BB. */
bitmap_set_bit (bb_info->use, DF_REF_REGNO (use)); bitmap_set_bit (bb_info->use, DF_REF_REGNO (use));
} }
/* Process the registers set in an exception handler. */ /* Process the registers set in an exception handler. */
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref) for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP)
&& (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL)))
{ {
unsigned int dregno = DF_REF_REGNO (def); unsigned int dregno = DF_REF_REGNO (def);
bitmap_set_bit (bb_info->def, dregno); bitmap_set_bit (bb_info->def, dregno);
...@@ -1493,6 +1512,7 @@ df_lr_bb_local_compute (struct dataflow *dflow, ...@@ -1493,6 +1512,7 @@ df_lr_bb_local_compute (struct dataflow *dflow,
#endif #endif
} }
/* Compute local live register info for each basic block within BLOCKS. */ /* Compute local live register info for each basic block within BLOCKS. */
static void static void
...@@ -1517,7 +1537,7 @@ df_lr_local_compute (struct dataflow *dflow, ...@@ -1517,7 +1537,7 @@ df_lr_local_compute (struct dataflow *dflow,
/* Before reload, there are a few registers that must be forced /* Before reload, there are a few registers that must be forced
live everywhere -- which might not already be the case for live everywhere -- which might not already be the case for
blocks within infinite loops. */ blocks within infinite loops. */
if (! reload_completed) if (!reload_completed)
{ {
/* Any reference to any pseudo before reload is a potential /* Any reference to any pseudo before reload is a potential
reference of the frame pointer. */ reference of the frame pointer. */
...@@ -1586,6 +1606,7 @@ df_lr_confluence_0 (struct dataflow *dflow, basic_block bb) ...@@ -1586,6 +1606,7 @@ df_lr_confluence_0 (struct dataflow *dflow, basic_block bb)
/* Confluence function that ignores fake edges. */ /* Confluence function that ignores fake edges. */
static void static void
df_lr_confluence_n (struct dataflow *dflow, edge e) df_lr_confluence_n (struct dataflow *dflow, edge e)
{ {
...@@ -1605,6 +1626,7 @@ df_lr_confluence_n (struct dataflow *dflow, edge e) ...@@ -1605,6 +1626,7 @@ df_lr_confluence_n (struct dataflow *dflow, edge e)
/* Transfer function. */ /* Transfer function. */
static bool static bool
df_lr_transfer_function (struct dataflow *dflow, int bb_index) df_lr_transfer_function (struct dataflow *dflow, int bb_index)
{ {
...@@ -1642,6 +1664,8 @@ df_lr_free (struct dataflow *dflow) ...@@ -1642,6 +1664,8 @@ df_lr_free (struct dataflow *dflow)
dflow->block_info_size = 0; dflow->block_info_size = 0;
free (dflow->block_info); free (dflow->block_info);
} }
free (dflow->problem_data);
free (dflow); free (dflow);
} }
...@@ -1653,6 +1677,9 @@ df_lr_dump (struct dataflow *dflow, FILE *file) ...@@ -1653,6 +1677,9 @@ df_lr_dump (struct dataflow *dflow, FILE *file)
{ {
basic_block bb; basic_block bb;
if (!dflow->block_info)
return;
fprintf (file, "Live Registers:\n"); fprintf (file, "Live Registers:\n");
FOR_ALL_BB (bb) FOR_ALL_BB (bb)
{ {
...@@ -1691,7 +1718,8 @@ static struct df_problem problem_LR = ...@@ -1691,7 +1718,8 @@ static struct df_problem problem_LR =
NULL, /* Finalize function. */ NULL, /* Finalize function. */
df_lr_free, /* Free all of the problem information. */ df_lr_free, /* Free all of the problem information. */
df_lr_dump, /* Debugging. */ df_lr_dump, /* Debugging. */
NULL /* Dependent problem. */ NULL, /* Dependent problem. */
0
}; };
...@@ -1700,9 +1728,9 @@ static struct df_problem problem_LR = ...@@ -1700,9 +1728,9 @@ static struct df_problem problem_LR =
solution. */ solution. */
struct dataflow * struct dataflow *
df_lr_add_problem (struct df *df) df_lr_add_problem (struct df *df, int flags)
{ {
return df_add_problem (df, &problem_LR); return df_add_problem (df, &problem_LR, flags);
} }
...@@ -1756,21 +1784,18 @@ df_ur_free_bb_info (struct dataflow *dflow, ...@@ -1756,21 +1784,18 @@ df_ur_free_bb_info (struct dataflow *dflow,
not touched unless the block is new. */ not touched unless the block is new. */
static void static void
df_ur_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_ur_alloc (struct dataflow *dflow, bitmap blocks_to_rescan,
bitmap all_blocks ATTRIBUTE_UNUSED)
{ {
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
if (! dflow->block_pool) if (!dflow->block_pool)
dflow->block_pool = create_alloc_pool ("df_ur_block pool", dflow->block_pool = create_alloc_pool ("df_ur_block pool",
sizeof (struct df_ur_bb_info), 100); sizeof (struct df_ur_bb_info), 100);
df_grow_bb_info (dflow); df_grow_bb_info (dflow);
/* Because of the clustering of all def sites for the same pseudo,
we have to process all of the blocks before doing the
analysis. */
EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi)
{ {
struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index); struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index);
...@@ -1823,16 +1848,23 @@ df_ur_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) ...@@ -1823,16 +1848,23 @@ df_ur_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
if (!INSN_P (insn)) if (!INSN_P (insn))
continue; continue;
for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
{ {
unsigned int regno = DF_REF_REGNO (def); unsigned int regno = DF_REF_REGNO (def);
/* Only the last def counts. */ /* Only the last def counts. */
if (!bitmap_bit_p (seen_in_block, regno)) if (!bitmap_bit_p (seen_in_block, regno))
{ {
bitmap_set_bit (seen_in_insn, regno); bitmap_set_bit (seen_in_insn, regno);
if (DF_REF_FLAGS (def) & DF_REF_CLOBBER) if (DF_REF_FLAGS (def)
bitmap_set_bit (bb_info->kill, regno); & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))
{
/* Only must clobbers for the entire reg destroy the
value. */
if ((DF_REF_FLAGS (def) & DF_REF_MUST_CLOBBER)
&& (!DF_REF_FLAGS (def) & DF_REF_PARTIAL))
bitmap_set_bit (bb_info->kill, regno);
}
else else
bitmap_set_bit (bb_info->gen, regno); bitmap_set_bit (bb_info->gen, regno);
} }
...@@ -1927,7 +1959,7 @@ df_ur_local_finalize (struct dataflow *dflow, bitmap all_blocks) ...@@ -1927,7 +1959,7 @@ df_ur_local_finalize (struct dataflow *dflow, bitmap all_blocks)
bitmap_and_into (bb_info->out, tmp); bitmap_and_into (bb_info->out, tmp);
#endif #endif
} }
BITMAP_FREE (tmp); BITMAP_FREE (tmp);
} }
...@@ -1998,6 +2030,9 @@ df_ur_dump (struct dataflow *dflow, FILE *file) ...@@ -1998,6 +2030,9 @@ df_ur_dump (struct dataflow *dflow, FILE *file)
{ {
basic_block bb; basic_block bb;
if (!dflow->block_info)
return;
fprintf (file, "Undefined regs:\n"); fprintf (file, "Undefined regs:\n");
FOR_ALL_BB (bb) FOR_ALL_BB (bb)
...@@ -2005,7 +2040,7 @@ df_ur_dump (struct dataflow *dflow, FILE *file) ...@@ -2005,7 +2040,7 @@ df_ur_dump (struct dataflow *dflow, FILE *file)
struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb->index); struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb->index);
df_print_bb_index (bb, file); df_print_bb_index (bb, file);
if (! bb_info->in) if (!bb_info->in)
continue; continue;
fprintf (file, " in \t"); fprintf (file, " in \t");
...@@ -2037,7 +2072,8 @@ static struct df_problem problem_UR = ...@@ -2037,7 +2072,8 @@ static struct df_problem problem_UR =
df_ur_local_finalize, /* Finalize function. */ df_ur_local_finalize, /* Finalize function. */
df_ur_free, /* Free all of the problem information. */ df_ur_free, /* Free all of the problem information. */
df_ur_dump, /* Debugging. */ df_ur_dump, /* Debugging. */
&problem_LR /* Dependent problem. */ df_lr_add_problem, /* Dependent problem. */
0 /* Changeable flags. */
}; };
...@@ -2046,9 +2082,9 @@ static struct df_problem problem_UR = ...@@ -2046,9 +2082,9 @@ static struct df_problem problem_UR =
solution. */ solution. */
struct dataflow * struct dataflow *
df_ur_add_problem (struct df *df) df_ur_add_problem (struct df *df, int flags)
{ {
return df_add_problem (df, &problem_UR); return df_add_problem (df, &problem_UR, flags);
} }
...@@ -2116,14 +2152,16 @@ df_urec_free_bb_info (struct dataflow *dflow, ...@@ -2116,14 +2152,16 @@ df_urec_free_bb_info (struct dataflow *dflow,
not touched unless the block is new. */ not touched unless the block is new. */
static void static void
df_urec_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_urec_alloc (struct dataflow *dflow, bitmap blocks_to_rescan,
bitmap all_blocks ATTRIBUTE_UNUSED)
{ {
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
struct df_urec_problem_data *problem_data = struct df_urec_problem_data *problem_data
(struct df_urec_problem_data *) dflow->problem_data; = (struct df_urec_problem_data *) dflow->problem_data;
if (! dflow->block_pool) if (!dflow->block_pool)
dflow->block_pool = create_alloc_pool ("df_urec_block pool", dflow->block_pool = create_alloc_pool ("df_urec_block pool",
sizeof (struct df_urec_bb_info), 50); sizeof (struct df_urec_bb_info), 50);
...@@ -2136,10 +2174,6 @@ df_urec_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) ...@@ -2136,10 +2174,6 @@ df_urec_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
df_grow_bb_info (dflow); df_grow_bb_info (dflow);
/* Because of the clustering of all def sites for the same pseudo,
we have to process all of the blocks before doing the
analysis. */
EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi) EXECUTE_IF_SET_IN_BITMAP (blocks_to_rescan, 0, bb_index, bi)
{ {
struct df_urec_bb_info *bb_info = df_urec_get_bb_info (dflow, bb_index); struct df_urec_bb_info *bb_info = df_urec_get_bb_info (dflow, bb_index);
...@@ -2376,11 +2410,10 @@ df_urec_bb_local_compute (struct dataflow *dflow, unsigned int bb_index) ...@@ -2376,11 +2410,10 @@ df_urec_bb_local_compute (struct dataflow *dflow, unsigned int bb_index)
if (INSN_P (insn)) if (INSN_P (insn))
{ {
note_stores (PATTERN (insn), df_urec_mark_reg_change, bb_info); note_stores (PATTERN (insn), df_urec_mark_reg_change, bb_info);
if (df_state & (DF_SCAN_GLOBAL | DF_SCAN_POST_ALLOC) if (df_urec_check_earlyclobber (insn))
&& df_urec_check_earlyclobber (insn))
{ {
struct df_urec_problem_data *problem_data = struct df_urec_problem_data *problem_data
(struct df_urec_problem_data *) dflow->problem_data; = (struct df_urec_problem_data *) dflow->problem_data;
problem_data->earlyclobbers_found = true; problem_data->earlyclobbers_found = true;
note_uses (&PATTERN (insn), note_uses (&PATTERN (insn),
df_urec_mark_reg_use_for_earlyclobber_1, bb_info); df_urec_mark_reg_use_for_earlyclobber_1, bb_info);
...@@ -2410,8 +2443,8 @@ df_urec_local_compute (struct dataflow *dflow, ...@@ -2410,8 +2443,8 @@ df_urec_local_compute (struct dataflow *dflow,
#ifdef STACK_REGS #ifdef STACK_REGS
int i; int i;
HARD_REG_SET zero, stack_hard_regs, used; HARD_REG_SET zero, stack_hard_regs, used;
struct df_urec_problem_data *problem_data = struct df_urec_problem_data *problem_data
(struct df_urec_problem_data *) dflow->problem_data; = (struct df_urec_problem_data *) dflow->problem_data;
/* Any register that MAY be allocated to a register stack (like the /* Any register that MAY be allocated to a register stack (like the
387) is treated poorly. Each such register is marked as being 387) is treated poorly. Each such register is marked as being
...@@ -2479,8 +2512,8 @@ df_urec_local_finalize (struct dataflow *dflow, bitmap all_blocks) ...@@ -2479,8 +2512,8 @@ df_urec_local_finalize (struct dataflow *dflow, bitmap all_blocks)
bitmap tmp = BITMAP_ALLOC (NULL); bitmap tmp = BITMAP_ALLOC (NULL);
bitmap_iterator bi; bitmap_iterator bi;
unsigned int bb_index; unsigned int bb_index;
struct df_urec_problem_data *problem_data = struct df_urec_problem_data *problem_data
(struct df_urec_problem_data *) dflow->problem_data; = (struct df_urec_problem_data *) dflow->problem_data;
EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi)
{ {
...@@ -2597,6 +2630,9 @@ df_urec_dump (struct dataflow *dflow, FILE *file) ...@@ -2597,6 +2630,9 @@ df_urec_dump (struct dataflow *dflow, FILE *file)
{ {
basic_block bb; basic_block bb;
if (!dflow->block_info)
return;
fprintf (file, "Undefined regs:\n"); fprintf (file, "Undefined regs:\n");
FOR_ALL_BB (bb) FOR_ALL_BB (bb)
...@@ -2604,7 +2640,7 @@ df_urec_dump (struct dataflow *dflow, FILE *file) ...@@ -2604,7 +2640,7 @@ df_urec_dump (struct dataflow *dflow, FILE *file)
struct df_urec_bb_info *bb_info = df_urec_get_bb_info (dflow, bb->index); struct df_urec_bb_info *bb_info = df_urec_get_bb_info (dflow, bb->index);
df_print_bb_index (bb, file); df_print_bb_index (bb, file);
if (! bb_info->in) if (!bb_info->in)
continue; continue;
fprintf (file, " in \t"); fprintf (file, " in \t");
...@@ -2638,7 +2674,8 @@ static struct df_problem problem_UREC = ...@@ -2638,7 +2674,8 @@ static struct df_problem problem_UREC =
df_urec_local_finalize, /* Finalize function. */ df_urec_local_finalize, /* Finalize function. */
df_urec_free, /* Free all of the problem information. */ df_urec_free, /* Free all of the problem information. */
df_urec_dump, /* Debugging. */ df_urec_dump, /* Debugging. */
&problem_LR /* Dependent problem. */ df_lr_add_problem, /* Dependent problem. */
0 /* Changeable flags. */
}; };
...@@ -2647,9 +2684,9 @@ static struct df_problem problem_UREC = ...@@ -2647,9 +2684,9 @@ static struct df_problem problem_UREC =
solution. */ solution. */
struct dataflow * struct dataflow *
df_urec_add_problem (struct df *df) df_urec_add_problem (struct df *df, int flags)
{ {
return df_add_problem (df, &problem_UREC); return df_add_problem (df, &problem_UREC, flags);
} }
...@@ -2665,22 +2702,16 @@ df_urec_add_problem (struct df *df) ...@@ -2665,22 +2702,16 @@ df_urec_add_problem (struct df *df)
the reaching defs information (the dependent problem). the reaching defs information (the dependent problem).
----------------------------------------------------------------------------*/ ----------------------------------------------------------------------------*/
struct df_chain_problem_data
{
int flags;
};
/* Create def-use or use-def chains. */ /* Create def-use or use-def chains. */
static void static void
df_chain_alloc (struct dataflow *dflow, df_chain_alloc (struct dataflow *dflow,
bitmap blocks_to_rescan ATTRIBUTE_UNUSED) bitmap blocks_to_rescan ATTRIBUTE_UNUSED,
bitmap all_blocks ATTRIBUTE_UNUSED)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
unsigned int i; unsigned int i;
struct df_chain_problem_data *problem_data =
(struct df_chain_problem_data *) dflow->problem_data;
/* Wholesale destruction of the old chains. */ /* Wholesale destruction of the old chains. */
if (dflow->block_pool) if (dflow->block_pool)
...@@ -2689,7 +2720,7 @@ df_chain_alloc (struct dataflow *dflow, ...@@ -2689,7 +2720,7 @@ df_chain_alloc (struct dataflow *dflow,
dflow->block_pool = create_alloc_pool ("df_chain_chain_block pool", dflow->block_pool = create_alloc_pool ("df_chain_chain_block pool",
sizeof (struct df_link), 100); sizeof (struct df_link), 100);
if (problem_data->flags & DF_DU_CHAIN) if (dflow->flags & DF_DU_CHAIN)
{ {
if (!df->def_info.refs_organized) if (!df->def_info.refs_organized)
df_reorganize_refs (&df->def_info); df_reorganize_refs (&df->def_info);
...@@ -2702,7 +2733,7 @@ df_chain_alloc (struct dataflow *dflow, ...@@ -2702,7 +2733,7 @@ df_chain_alloc (struct dataflow *dflow,
} }
} }
if (problem_data->flags & DF_UD_CHAIN) if (dflow->flags & DF_UD_CHAIN)
{ {
if (!df->use_info.refs_organized) if (!df->use_info.refs_organized)
df_reorganize_refs (&df->use_info); df_reorganize_refs (&df->use_info);
...@@ -2721,8 +2752,6 @@ static void ...@@ -2721,8 +2752,6 @@ static void
df_chain_insn_reset (struct dataflow *dflow, rtx insn) df_chain_insn_reset (struct dataflow *dflow, rtx insn)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_chain_problem_data *problem_data =
(struct df_chain_problem_data *) dflow->problem_data;
unsigned int uid = INSN_UID (insn); unsigned int uid = INSN_UID (insn);
struct df_insn_info *insn_info = NULL; struct df_insn_info *insn_info = NULL;
struct df_ref *ref; struct df_ref *ref;
...@@ -2732,7 +2761,7 @@ df_chain_insn_reset (struct dataflow *dflow, rtx insn) ...@@ -2732,7 +2761,7 @@ df_chain_insn_reset (struct dataflow *dflow, rtx insn)
if (insn_info) if (insn_info)
{ {
if (problem_data->flags & DF_DU_CHAIN) if (dflow->flags & DF_DU_CHAIN)
{ {
ref = insn_info->defs; ref = insn_info->defs;
while (ref) while (ref)
...@@ -2742,7 +2771,7 @@ df_chain_insn_reset (struct dataflow *dflow, rtx insn) ...@@ -2742,7 +2771,7 @@ df_chain_insn_reset (struct dataflow *dflow, rtx insn)
} }
} }
if (problem_data->flags & DF_UD_CHAIN) if (dflow->flags & DF_UD_CHAIN)
{ {
ref = insn_info->uses; ref = insn_info->uses;
while (ref) while (ref)
...@@ -2761,8 +2790,6 @@ static void ...@@ -2761,8 +2790,6 @@ static void
df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index) df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_chain_problem_data *problem_data =
(struct df_chain_problem_data *) dflow->problem_data;
rtx insn; rtx insn;
basic_block bb = BASIC_BLOCK (bb_index); basic_block bb = BASIC_BLOCK (bb_index);
...@@ -2780,7 +2807,7 @@ df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index) ...@@ -2780,7 +2807,7 @@ df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index)
} }
/* Get rid of any chains in artificial uses or defs. */ /* Get rid of any chains in artificial uses or defs. */
if (problem_data->flags & DF_DU_CHAIN) if (dflow->flags & DF_DU_CHAIN)
{ {
struct df_ref *def; struct df_ref *def;
def = df_get_artificial_defs (df, bb_index); def = df_get_artificial_defs (df, bb_index);
...@@ -2791,7 +2818,7 @@ df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index) ...@@ -2791,7 +2818,7 @@ df_chain_bb_reset (struct dataflow *dflow, unsigned int bb_index)
} }
} }
if (problem_data->flags & DF_UD_CHAIN) if (dflow->flags & DF_UD_CHAIN)
{ {
struct df_ref *use; struct df_ref *use;
use = df_get_artificial_uses (df, bb_index); use = df_get_artificial_uses (df, bb_index);
...@@ -2827,7 +2854,6 @@ df_chain_reset (struct dataflow *dflow, bitmap blocks_to_clear) ...@@ -2827,7 +2854,6 @@ df_chain_reset (struct dataflow *dflow, bitmap blocks_to_clear)
static void static void
df_chain_create_bb_process_use (struct dataflow *dflow, df_chain_create_bb_process_use (struct dataflow *dflow,
struct df_chain_problem_data *problem_data,
bitmap local_rd, bitmap local_rd,
struct df_ref *use, struct df_ref *use,
enum df_ref_flags top_flag) enum df_ref_flags top_flag)
...@@ -2855,9 +2881,9 @@ df_chain_create_bb_process_use (struct dataflow *dflow, ...@@ -2855,9 +2881,9 @@ df_chain_create_bb_process_use (struct dataflow *dflow,
break; break;
def = DF_DEFS_GET (df, def_index); def = DF_DEFS_GET (df, def_index);
if (problem_data->flags & DF_DU_CHAIN) if (dflow->flags & DF_DU_CHAIN)
df_chain_create (dflow, def, use); df_chain_create (dflow, def, use);
if (problem_data->flags & DF_UD_CHAIN) if (dflow->flags & DF_UD_CHAIN)
df_chain_create (dflow, use, def); df_chain_create (dflow, use, def);
} }
} }
...@@ -2881,8 +2907,6 @@ df_chain_create_bb (struct dataflow *dflow, ...@@ -2881,8 +2907,6 @@ df_chain_create_bb (struct dataflow *dflow,
rtx insn; rtx insn;
bitmap cpy = BITMAP_ALLOC (NULL); bitmap cpy = BITMAP_ALLOC (NULL);
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_chain_problem_data *problem_data =
(struct df_chain_problem_data *) dflow->problem_data;
struct df_ref *def; struct df_ref *def;
bitmap_copy (cpy, bb_info->in); bitmap_copy (cpy, bb_info->in);
...@@ -2893,7 +2917,7 @@ df_chain_create_bb (struct dataflow *dflow, ...@@ -2893,7 +2917,7 @@ df_chain_create_bb (struct dataflow *dflow,
#ifdef EH_USES #ifdef EH_USES
/* Create the chains for the artificial uses from the EH_USES at the /* Create the chains for the artificial uses from the EH_USES at the
beginning of the block. */ beginning of the block. */
df_chain_create_bb_process_use (dflow, problem_data, cpy, df_chain_create_bb_process_use (dflow, cpy,
df_get_artificial_uses (df, bb->index), df_get_artificial_uses (df, bb->index),
DF_REF_AT_TOP); DF_REF_AT_TOP);
#endif #endif
...@@ -2902,11 +2926,11 @@ df_chain_create_bb (struct dataflow *dflow, ...@@ -2902,11 +2926,11 @@ df_chain_create_bb (struct dataflow *dflow,
if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
{ {
unsigned int dregno = DF_REF_REGNO (def); unsigned int dregno = DF_REF_REGNO (def);
bitmap_clear_range (cpy, if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
DF_REG_DEF_GET (df, dregno)->begin, bitmap_clear_range (cpy,
DF_REG_DEF_GET (df, dregno)->n_refs); DF_REG_DEF_GET (df, dregno)->begin,
if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER)) DF_REG_DEF_GET (df, dregno)->n_refs);
bitmap_set_bit (cpy, DF_REF_ID (def)); bitmap_set_bit (cpy, DF_REF_ID (def));
} }
/* Process the regular instructions next. */ /* Process the regular instructions next. */
...@@ -2915,31 +2939,33 @@ df_chain_create_bb (struct dataflow *dflow, ...@@ -2915,31 +2939,33 @@ df_chain_create_bb (struct dataflow *dflow,
struct df_ref *def; struct df_ref *def;
unsigned int uid = INSN_UID (insn); unsigned int uid = INSN_UID (insn);
if (! INSN_P (insn)) if (!INSN_P (insn))
continue; continue;
/* Now scan the uses and link them up with the defs that remain /* Now scan the uses and link them up with the defs that remain
in the cpy vector. */ in the cpy vector. */
df_chain_create_bb_process_use (dflow, problem_data, cpy, df_chain_create_bb_process_use (dflow, cpy,
DF_INSN_UID_GET (df, uid)->uses, 0); DF_INSN_UID_USES (df, uid), 0);
/* Since we are going forwards, process the defs second. This /* Since we are going forwards, process the defs second. This
pass only changes the bits in cpy. */ pass only changes the bits in cpy. */
for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
{ {
unsigned int dregno = DF_REF_REGNO (def); unsigned int dregno = DF_REF_REGNO (def);
bitmap_clear_range (cpy, if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
DF_REG_DEF_GET (df, dregno)->begin, bitmap_clear_range (cpy,
DF_REG_DEF_GET (df, dregno)->n_refs); DF_REG_DEF_GET (df, dregno)->begin,
if (! (DF_REF_FLAGS (def) & DF_REF_CLOBBER)) DF_REG_DEF_GET (df, dregno)->n_refs);
if (!(DF_REF_FLAGS (def)
& (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
bitmap_set_bit (cpy, DF_REF_ID (def)); bitmap_set_bit (cpy, DF_REF_ID (def));
} }
} }
/* Create the chains for the artificial uses of the hard registers /* Create the chains for the artificial uses of the hard registers
at the end of the block. */ at the end of the block. */
df_chain_create_bb_process_use (dflow, problem_data, cpy, df_chain_create_bb_process_use (dflow, cpy,
df_get_artificial_uses (df, bb->index), 0); df_get_artificial_uses (df, bb->index), 0);
} }
...@@ -2967,7 +2993,6 @@ static void ...@@ -2967,7 +2993,6 @@ static void
df_chain_free (struct dataflow *dflow) df_chain_free (struct dataflow *dflow)
{ {
free_alloc_pool (dflow->block_pool); free_alloc_pool (dflow->block_pool);
free (dflow->problem_data);
free (dflow); free (dflow);
} }
...@@ -2979,10 +3004,8 @@ df_chains_dump (struct dataflow *dflow, FILE *file) ...@@ -2979,10 +3004,8 @@ df_chains_dump (struct dataflow *dflow, FILE *file)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
unsigned int j; unsigned int j;
struct df_chain_problem_data *problem_data =
(struct df_chain_problem_data *) dflow->problem_data;
if (problem_data->flags & DF_DU_CHAIN) if (dflow->flags & DF_DU_CHAIN)
{ {
fprintf (file, "Def-use chains:\n"); fprintf (file, "Def-use chains:\n");
for (j = 0; j < df->def_info.bitmap_size; j++) for (j = 0; j < df->def_info.bitmap_size; j++)
...@@ -2999,13 +3022,13 @@ df_chains_dump (struct dataflow *dflow, FILE *file) ...@@ -2999,13 +3022,13 @@ df_chains_dump (struct dataflow *dflow, FILE *file)
DF_REF_REGNO (def)); DF_REF_REGNO (def));
if (def->flags & DF_REF_READ_WRITE) if (def->flags & DF_REF_READ_WRITE)
fprintf (file, "read/write "); fprintf (file, "read/write ");
df_chain_dump (df, DF_REF_CHAIN (def), file); df_chain_dump (DF_REF_CHAIN (def), file);
fprintf (file, "\n"); fprintf (file, "\n");
} }
} }
} }
if (problem_data->flags & DF_UD_CHAIN) if (dflow->flags & DF_UD_CHAIN)
{ {
fprintf (file, "Use-def chains:\n"); fprintf (file, "Use-def chains:\n");
for (j = 0; j < df->use_info.bitmap_size; j++) for (j = 0; j < df->use_info.bitmap_size; j++)
...@@ -3028,7 +3051,7 @@ df_chains_dump (struct dataflow *dflow, FILE *file) ...@@ -3028,7 +3051,7 @@ df_chains_dump (struct dataflow *dflow, FILE *file)
fprintf (file, "stripped "); fprintf (file, "stripped ");
if (use->flags & DF_REF_IN_NOTE) if (use->flags & DF_REF_IN_NOTE)
fprintf (file, "note "); fprintf (file, "note ");
df_chain_dump (df, DF_REF_CHAIN (use), file); df_chain_dump (DF_REF_CHAIN (use), file);
fprintf (file, "\n"); fprintf (file, "\n");
} }
} }
...@@ -3052,7 +3075,8 @@ static struct df_problem problem_CHAIN = ...@@ -3052,7 +3075,8 @@ static struct df_problem problem_CHAIN =
df_chain_finalize, /* Finalize function. */ df_chain_finalize, /* Finalize function. */
df_chain_free, /* Free all of the problem information. */ df_chain_free, /* Free all of the problem information. */
df_chains_dump, /* Debugging. */ df_chains_dump, /* Debugging. */
&problem_RD /* Dependent problem. */ df_rd_add_problem, /* Dependent problem. */
0 /* Changeable flags. */
}; };
...@@ -3063,104 +3087,560 @@ static struct df_problem problem_CHAIN = ...@@ -3063,104 +3087,560 @@ static struct df_problem problem_CHAIN =
struct dataflow * struct dataflow *
df_chain_add_problem (struct df *df, int flags) df_chain_add_problem (struct df *df, int flags)
{ {
struct df_chain_problem_data *problem_data = return df_add_problem (df, &problem_CHAIN, flags);
XNEW (struct df_chain_problem_data);
struct dataflow *dflow = df_add_problem (df, &problem_CHAIN);
dflow->problem_data = problem_data;
problem_data->flags = flags;
return dflow;
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
REGISTER INFORMATION REGISTER INFORMATION
Currently this consists of only lifetime information. But the plan is Currently this consists of only lifetime information and reg_dead
to enhance it so that it produces all of the register information needed and reg_unused.
by the register allocators. ----------------------------------------------------------------------------*/
----------------------------------------------------------------------------*/
struct df_ri_problem_data #ifdef REG_DEAD_DEBUGGING
static void
print_note (char *prefix, rtx insn, rtx note)
{ {
int *lifetime; fprintf (stderr, "%s %d ", prefix, INSN_UID (insn));
}; print_rtl (stderr, note);
fprintf (stderr, "\n");
}
#endif
/* Allocate the lifetime information. */ /* Allocate the lifetime information. */
static void static void
df_ri_alloc (struct dataflow *dflow, bitmap blocks_to_rescan ATTRIBUTE_UNUSED) df_ri_alloc (struct dataflow *dflow,
bitmap blocks_to_rescan ATTRIBUTE_UNUSED,
bitmap all_blocks ATTRIBUTE_UNUSED)
{ {
struct df_ri_problem_data *problem_data = int i;
(struct df_ri_problem_data *) dflow->problem_data; struct df *df = dflow->df;
if (!dflow->problem_data) if (dflow->flags & DF_RI_LIFE)
{ {
struct df_ri_problem_data *problem_data = XNEW (struct df_ri_problem_data); max_regno = max_reg_num ();
dflow->problem_data = problem_data; allocate_reg_info (max_regno, FALSE, FALSE);
/* Reset all the data we'll collect. */
for (i = 0; i < max_regno; i++)
{
REG_N_SETS (i) = DF_REG_DEF_COUNT (df, i);
REG_N_REFS (i) = DF_REG_USE_COUNT (df, i) + REG_N_SETS (i);
REG_N_DEATHS (i) = 0;
REG_N_CALLS_CROSSED (i) = 0;
REG_N_THROWING_CALLS_CROSSED (i) = 0;
REG_LIVE_LENGTH (i) = 0;
REG_FREQ (i) = 0;
REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
}
}
}
/* After reg-stack, the x86 floating point stack regs are difficult to
analyze because of all of the pushes, pops and rotations. Thus, we
just leave the notes alone. */
static inline bool
df_ignore_stack_reg (int regno ATTRIBUTE_UNUSED)
{
#ifdef STACK_REGS
return (regstack_completed
&& IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG));
#else
return false;
#endif
}
/* Remove all of the REG_DEAD or REG_UNUSED notes from INSN. */
static void
df_kill_notes (rtx insn, int flags)
{
rtx *pprev = &REG_NOTES (insn);
rtx link = *pprev;
while (link)
{
switch (REG_NOTE_KIND (link))
{
case REG_DEAD:
if (flags & DF_RI_LIFE)
if (df_ignore_stack_reg (REGNO (XEXP (link, 0))))
REG_N_DEATHS (REGNO (XEXP (link, 0)))++;
/* Fallthru */
case REG_UNUSED:
if (!df_ignore_stack_reg (REGNO (XEXP (link, 0))))
{
rtx next = XEXP (link, 1);
#ifdef REG_DEAD_DEBUGGING
print_note ("deleting: ", insn, link);
#endif
free_EXPR_LIST_node (link);
*pprev = link = next;
}
break;
default:
pprev = &XEXP (link, 1);
link = *pprev;
break;
}
}
}
/* Set the REG_UNUSED notes for the multiword hardreg defs in INSN
based on the bits in LIVE. Do not generate notes for registers in
artificial uses. DO_NOT_GEN is updated so that REG_DEAD notes are
not generated if the reg is both read and written by the
instruction.
*/
static void
df_set_unused_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
bitmap live, bitmap do_not_gen,
bitmap artificial_uses, int flags)
{
bool all_dead = true;
struct df_link *regs = mws->regs;
unsigned int regno = DF_REF_REGNO (regs->ref);
#ifdef REG_DEAD_DEBUGGING
fprintf (stderr, "mw unused looking at %d\n", DF_REF_REGNO (regs->ref));
df_ref_debug (regs->ref, stderr);
#endif
while (regs)
{
unsigned int regno = DF_REF_REGNO (regs->ref);
if ((bitmap_bit_p (live, regno))
|| bitmap_bit_p (artificial_uses, regno))
{
all_dead = false;
break;
}
regs = regs->next;
}
if (all_dead)
{
struct df_link *regs = mws->regs;
rtx note = alloc_EXPR_LIST (REG_UNUSED, *DF_REF_LOC (regs->ref),
REG_NOTES (insn));
REG_NOTES (insn) = note;
#ifdef REG_DEAD_DEBUGGING
print_note ("adding 1: ", insn, note);
#endif
bitmap_set_bit (do_not_gen, regno);
/* Only do this if the value is totally dead. */
if (flags & DF_RI_LIFE)
{
REG_N_DEATHS (regno) ++;
REG_LIVE_LENGTH (regno)++;
}
}
else
{
struct df_link *regs = mws->regs;
while (regs)
{
struct df_ref *ref = regs->ref;
regno = DF_REF_REGNO (ref);
if ((!bitmap_bit_p (live, regno))
&& (!bitmap_bit_p (artificial_uses, regno)))
{
rtx note = alloc_EXPR_LIST (REG_UNUSED, regno_reg_rtx[regno],
REG_NOTES (insn));
REG_NOTES (insn) = note;
#ifdef REG_DEAD_DEBUGGING
print_note ("adding 2: ", insn, note);
#endif
}
bitmap_set_bit (do_not_gen, regno);
regs = regs->next;
}
}
}
/* Set the REG_DEAD notes for the multiword hardreg use in INSN based
on the bits in LIVE. DO_NOT_GEN is used to keep REG_DEAD notes
from being set if the instruction both reads and writes the
register. */
static void
df_set_dead_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
bitmap live, bitmap do_not_gen,
bitmap artificial_uses, int flags)
{
bool all_dead = true;
struct df_link *regs = mws->regs;
unsigned int regno = DF_REF_REGNO (regs->ref);
#ifdef REG_DEAD_DEBUGGING
fprintf (stderr, "mw looking at %d\n", DF_REF_REGNO (regs->ref));
df_ref_debug (regs->ref, stderr);
#endif
while (regs)
{
unsigned int regno = DF_REF_REGNO (regs->ref);
if ((bitmap_bit_p (live, regno))
|| bitmap_bit_p (artificial_uses, regno))
{
all_dead = false;
break;
}
regs = regs->next;
}
if (all_dead)
{
if (!bitmap_bit_p (do_not_gen, regno))
{
/* Add a dead note for the entire multi word register. */
struct df_link *regs = mws->regs;
rtx note = alloc_EXPR_LIST (REG_DEAD, *DF_REF_LOC (regs->ref),
REG_NOTES (insn));
REG_NOTES (insn) = note;
#ifdef REG_DEAD_DEBUGGING
print_note ("adding 1: ", insn, note);
#endif
if (flags & DF_RI_LIFE)
{
struct df_link *regs = mws->regs;
while (regs)
{
struct df_ref *ref = regs->ref;
regno = DF_REF_REGNO (ref);
REG_N_DEATHS (regno)++;
regs = regs->next;
}
}
}
}
else
{
struct df_link *regs = mws->regs;
while (regs)
{
struct df_ref *ref = regs->ref;
regno = DF_REF_REGNO (ref);
if ((!bitmap_bit_p (live, regno))
&& (!bitmap_bit_p (artificial_uses, regno))
&& (!bitmap_bit_p (do_not_gen, regno)))
{
rtx note = alloc_EXPR_LIST (REG_DEAD, regno_reg_rtx[regno],
REG_NOTES (insn));
REG_NOTES (insn) = note;
if (flags & DF_RI_LIFE)
REG_N_DEATHS (regno)++;
#ifdef REG_DEAD_DEBUGGING
print_note ("adding 2: ", insn, note);
#endif
}
regs = regs->next;
}
}
}
/* Create a REG_UNUSED note if necessary for DEF in INSN updating LIVE
and DO_NOT_GEN. Do not generate notes for registers in artificial
uses. */
static void
df_create_unused_note (basic_block bb, rtx insn, struct df_ref *def,
bitmap live, bitmap do_not_gen, bitmap artificial_uses,
bitmap local_live, bitmap local_processed,
int flags, int luid)
{
unsigned int dregno = DF_REF_REGNO (def);
#ifdef REG_DEAD_DEBUGGING
fprintf (stderr, " regular looking at def ");
df_ref_debug (def, stderr);
#endif
if (bitmap_bit_p (live, dregno))
{
if (flags & DF_RI_LIFE)
{
/* If we have seen this regno, then it has already been
processed correctly with the per insn increment. If we
have not seen it we need to add the length from here to
the end of the block to the live length. */
if (bitmap_bit_p (local_processed, dregno))
{
if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
bitmap_clear_bit (local_live, dregno);
}
else
{
bitmap_set_bit (local_processed, dregno);
REG_LIVE_LENGTH (dregno) += luid;
}
}
}
else if ((!(DF_REF_FLAGS (def) & DF_REF_MW_HARDREG))
&& (!bitmap_bit_p (artificial_uses, dregno))
&& (!df_ignore_stack_reg (dregno)))
{
rtx reg = GET_CODE (*DF_REF_LOC (def)) == SUBREG ?
SUBREG_REG (*DF_REF_LOC (def)) : *DF_REF_LOC (def);
rtx note = alloc_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
REG_NOTES (insn) = note;
#ifdef REG_DEAD_DEBUGGING
print_note ("adding 3: ", insn, note);
#endif
if (flags & DF_RI_LIFE)
{
REG_N_DEATHS (dregno) ++;
REG_LIVE_LENGTH (dregno)++;
}
}
if ((flags & DF_RI_LIFE) && (dregno >= FIRST_PSEUDO_REGISTER))
{
REG_FREQ (dregno) += REG_FREQ_FROM_BB (bb);
if (REG_BASIC_BLOCK (dregno) == REG_BLOCK_UNKNOWN)
REG_BASIC_BLOCK (dregno) = bb->index;
else if (REG_BASIC_BLOCK (dregno) != bb->index)
REG_BASIC_BLOCK (dregno) = REG_BLOCK_GLOBAL;
} }
problem_data->lifetime = xrealloc (problem_data->lifetime, if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER + DF_REF_MAY_CLOBBER)))
max_reg_num () *sizeof (int)); bitmap_set_bit (do_not_gen, dregno);
memset (problem_data->lifetime, 0, max_reg_num () *sizeof (int));
/* Kill this register if it is not a subreg store. */
if (!(DF_REF_FLAGS (def) & DF_REF_PARTIAL))
bitmap_clear_bit (live, dregno);
} }
/* Compute register info: lifetime, bb, and number of defs and uses
for basic block BB. */ /* Recompute the REG_DEAD and REG_UNUSED notes and compute register
info: lifetime, bb, and number of defs and uses for basic block
BB. The three bitvectors are scratch regs used here. */
static void static void
df_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index, bitmap live) df_ri_bb_compute (struct dataflow *dflow, unsigned int bb_index,
bitmap live, bitmap do_not_gen, bitmap artificial_uses,
bitmap local_live, bitmap local_processed, bitmap setjumps_crossed)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_ur_bb_info *bb_info = df_ur_get_bb_info (dflow, bb_index);
struct df_ri_problem_data *problem_data =
(struct df_ri_problem_data *) dflow->problem_data;
basic_block bb = BASIC_BLOCK (bb_index); basic_block bb = BASIC_BLOCK (bb_index);
rtx insn; rtx insn;
struct df_ref *def;
struct df_ref *use;
int luid = 0;
bitmap_copy (live, df_get_live_out (df, bb));
bitmap_clear (artificial_uses);
if (dflow->flags & DF_RI_LIFE)
{
/* Process the regs live at the end of the block. Mark them as
not local to any one basic block. */
bitmap_iterator bi;
unsigned int regno;
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL;
}
/* Process the artificial defs and uses at the bottom of the block
to begin processing. */
for (def = df_get_artificial_defs (df, bb_index); def; def = def->next_ref)
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
bitmap_clear_bit (live, DF_REF_REGNO (def));
bitmap_copy (live, bb_info->out); for (use = df_get_artificial_uses (df, bb_index); use; use = use->next_ref)
if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
{
unsigned int regno = DF_REF_REGNO (use);
bitmap_set_bit (live, regno);
/* Notes are not generated for any of the artificial registers
at the bottom of the block. */
bitmap_set_bit (artificial_uses, regno);
}
FOR_BB_INSNS_REVERSE (bb, insn) FOR_BB_INSNS_REVERSE (bb, insn)
{ {
unsigned int uid = INSN_UID (insn); unsigned int uid = INSN_UID (insn);
unsigned int regno; unsigned int regno;
bitmap_iterator bi; bitmap_iterator bi;
struct df_ref *def; struct df_mw_hardreg *mws;
struct df_ref *use;
if (!INSN_P (insn))
if (! INSN_P (insn))
continue; continue;
for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref) if (dflow->flags & DF_RI_LIFE)
{ {
unsigned int dregno = DF_REF_REGNO (def); /* Increment the live_length for all of the registers that
are are referenced in this block and live at this
particular point. */
bitmap_iterator bi;
unsigned int regno;
EXECUTE_IF_SET_IN_BITMAP (local_live, 0, regno, bi)
{
REG_LIVE_LENGTH (regno)++;
}
luid++;
}
bitmap_clear (do_not_gen);
df_kill_notes (insn, dflow->flags);
/* Process the defs. */
if (CALL_P (insn))
{
if (dflow->flags & DF_RI_LIFE)
{
bool can_throw = can_throw_internal (insn);
bool set_jump = (find_reg_note (insn, REG_SETJMP, NULL) != NULL);
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
{
REG_N_CALLS_CROSSED (regno)++;
if (can_throw)
REG_N_THROWING_CALLS_CROSSED (regno)++;
/* We have a problem with any pseudoreg that lives
across the setjmp. ANSI says that if a user
variable does not change in value between the
setjmp and the longjmp, then the longjmp
preserves it. This includes longjmp from a place
where the pseudo appears dead. (In principle,
the value still exists if it is in scope.) If
the pseudo goes in a hard reg, some other value
may occupy that hard reg where this pseudo is
dead, thus clobbering the pseudo. Conclusion:
such a pseudo must not go in a hard reg. */
if (set_jump && regno >= FIRST_PSEUDO_REGISTER)
bitmap_set_bit (setjumps_crossed, regno);
}
}
/* We only care about real sets for calls. Clobbers only
may clobber and cannot be depended on. */
for (mws = DF_INSN_UID_MWS (df, uid); mws; mws = mws->next)
{
if ((mws->type == DF_REF_REG_DEF)
&& !df_ignore_stack_reg (REGNO (mws->mw_reg)))
df_set_unused_notes_for_mw (insn, mws, live, do_not_gen,
artificial_uses, dflow->flags);
}
/* All of the defs except the return value are some sort of
clobber. This code is for the return. */
for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
df_create_unused_note (bb, insn, def, live, do_not_gen,
artificial_uses, local_live,
local_processed, dflow->flags, luid);
/* Kill this register. */ }
bitmap_clear_bit (live, dregno); else
{
/* Regular insn. */
for (mws = DF_INSN_UID_MWS (df, uid); mws; mws = mws->next)
{
if (mws->type == DF_REF_REG_DEF)
df_set_unused_notes_for_mw (insn, mws, live, do_not_gen,
artificial_uses, dflow->flags);
}
for (def = DF_INSN_UID_DEFS (df, uid); def; def = def->next_ref)
df_create_unused_note (bb, insn, def, live, do_not_gen,
artificial_uses, local_live,
local_processed, dflow->flags, luid);
}
/* Process the uses. */
for (mws = DF_INSN_UID_MWS (df, uid); mws; mws = mws->next)
{
if ((mws->type != DF_REF_REG_DEF)
&& !df_ignore_stack_reg (REGNO (mws->mw_reg)))
df_set_dead_notes_for_mw (insn, mws, live, do_not_gen,
artificial_uses, dflow->flags);
} }
for (use = DF_INSN_UID_GET (df, uid)->uses; use; use = use->next_ref) for (use = DF_INSN_UID_USES (df, uid); use; use = use->next_ref)
{ {
unsigned int uregno = DF_REF_REGNO (use); unsigned int uregno = DF_REF_REGNO (use);
if ((dflow->flags & DF_RI_LIFE) && (uregno >= FIRST_PSEUDO_REGISTER))
{
REG_FREQ (uregno) += REG_FREQ_FROM_BB (bb);
if (REG_BASIC_BLOCK (uregno) == REG_BLOCK_UNKNOWN)
REG_BASIC_BLOCK (uregno) = bb->index;
else if (REG_BASIC_BLOCK (uregno) != bb->index)
REG_BASIC_BLOCK (uregno) = REG_BLOCK_GLOBAL;
}
#ifdef REG_DEAD_DEBUGGING
fprintf (stderr, " regular looking at use ");
df_ref_debug (use, stderr);
#endif
if (!bitmap_bit_p (live, uregno)) if (!bitmap_bit_p (live, uregno))
{ {
use->flags |= DF_REF_DIES_AFTER_THIS_USE; if ( (!(DF_REF_FLAGS (use) & DF_REF_MW_HARDREG))
&& (!bitmap_bit_p (do_not_gen, uregno))
&& (!bitmap_bit_p (artificial_uses, uregno))
&& (!(DF_REF_FLAGS (use) & DF_REF_READ_WRITE))
&& (!df_ignore_stack_reg (uregno)))
{
rtx reg = GET_CODE (*DF_REF_LOC (use)) == SUBREG ?
SUBREG_REG (*DF_REF_LOC (use)) : *DF_REF_LOC (use);
rtx note = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn));
REG_NOTES (insn) = note;
if (dflow->flags & DF_RI_LIFE)
REG_N_DEATHS (uregno)++;
#ifdef REG_DEAD_DEBUGGING
print_note ("adding 4: ", insn, note);
#endif
}
/* This register is now live. */ /* This register is now live. */
bitmap_set_bit (live, uregno); bitmap_set_bit (live, uregno);
if (dflow->flags & DF_RI_LIFE)
{
/* If we have seen this regno, then it has already
been processed correctly with the per insn
increment. If we have not seen it we set the bit
so that begins to get processed locally. Note
that we don't even get here if the variable was
live at the end of the block since just a ref
inside the block does not effect the
calculations. */
REG_LIVE_LENGTH (uregno) ++;
bitmap_set_bit (local_live, uregno);
bitmap_set_bit (local_processed, uregno);
}
} }
else
use->flags &= ~DF_REF_DIES_AFTER_THIS_USE;
} }
}
/* Increment lifetimes of all live registers. */
if (dflow->flags & DF_RI_LIFE)
{
/* Add the length of the block to all of the registers that were
not referenced, but still live in this block. */
bitmap_iterator bi;
unsigned int regno;
bitmap_and_compl_into (live, local_processed);
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi) EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
{ {
problem_data->lifetime[regno]++; REG_LIVE_LENGTH (regno) += luid;
} }
bitmap_clear (local_processed);
bitmap_clear (local_live);
} }
} }
...@@ -3172,16 +3652,50 @@ df_ri_compute (struct dataflow *dflow, bitmap all_blocks ATTRIBUTE_UNUSED, ...@@ -3172,16 +3652,50 @@ df_ri_compute (struct dataflow *dflow, bitmap all_blocks ATTRIBUTE_UNUSED,
{ {
unsigned int bb_index; unsigned int bb_index;
bitmap_iterator bi; bitmap_iterator bi;
bitmap live; bitmap live = BITMAP_ALLOC (NULL);
bitmap do_not_gen = BITMAP_ALLOC (NULL);
bitmap artificial_uses = BITMAP_ALLOC (NULL);
bitmap local_live = NULL;
bitmap local_processed = NULL;
bitmap setjumps_crossed = NULL;
if (dflow->flags & DF_RI_LIFE)
{
local_live = BITMAP_ALLOC (NULL);
local_processed = BITMAP_ALLOC (NULL);
setjumps_crossed = BITMAP_ALLOC (NULL);
}
live = BITMAP_ALLOC (NULL);
#ifdef REG_DEAD_DEBUGGING
df_lr_dump (dflow->df->problems_by_index [DF_LR], stderr);
print_rtl_with_bb (stderr, get_insns());
#endif
EXECUTE_IF_SET_IN_BITMAP (blocks_to_scan, 0, bb_index, bi) EXECUTE_IF_SET_IN_BITMAP (blocks_to_scan, 0, bb_index, bi)
{ {
df_ri_bb_compute (dflow, bb_index, live); df_ri_bb_compute (dflow, bb_index, live, do_not_gen, artificial_uses,
local_live, local_processed, setjumps_crossed);
} }
BITMAP_FREE (live); BITMAP_FREE (live);
BITMAP_FREE (do_not_gen);
BITMAP_FREE (artificial_uses);
if (dflow->flags & DF_RI_LIFE)
{
bitmap_iterator bi;
unsigned int regno;
/* See the setjump comment in df_ri_bb_compute. */
EXECUTE_IF_SET_IN_BITMAP (setjumps_crossed, 0, regno, bi)
{
REG_BASIC_BLOCK (regno) = REG_BLOCK_UNKNOWN;
REG_LIVE_LENGTH (regno) = -1;
}
BITMAP_FREE (local_live);
BITMAP_FREE (local_processed);
BITMAP_FREE (setjumps_crossed);
}
} }
...@@ -3190,10 +3704,6 @@ df_ri_compute (struct dataflow *dflow, bitmap all_blocks ATTRIBUTE_UNUSED, ...@@ -3190,10 +3704,6 @@ df_ri_compute (struct dataflow *dflow, bitmap all_blocks ATTRIBUTE_UNUSED,
static void static void
df_ri_free (struct dataflow *dflow) df_ri_free (struct dataflow *dflow)
{ {
struct df_ri_problem_data *problem_data =
(struct df_ri_problem_data *) dflow->problem_data;
free (problem_data->lifetime);
free (dflow->problem_data); free (dflow->problem_data);
free (dflow); free (dflow);
} }
...@@ -3204,14 +3714,12 @@ df_ri_free (struct dataflow *dflow) ...@@ -3204,14 +3714,12 @@ df_ri_free (struct dataflow *dflow)
static void static void
df_ri_dump (struct dataflow *dflow, FILE *file) df_ri_dump (struct dataflow *dflow, FILE *file)
{ {
struct df_ri_problem_data *problem_data = print_rtl_with_bb (file, get_insns ());
(struct df_ri_problem_data *) dflow->problem_data;
int j;
fprintf (file, "Register info:\n"); if (dflow->flags & DF_RI_LIFE)
for (j = 0; j < max_reg_num (); j++)
{ {
fprintf (file, "reg %d life %d\n", j, problem_data->lifetime[j]); fprintf (file, "Register info:\n");
dump_flow_info (file, -1);
} }
} }
...@@ -3233,7 +3741,12 @@ static struct df_problem problem_RI = ...@@ -3233,7 +3741,12 @@ static struct df_problem problem_RI =
NULL, /* Finalize function. */ NULL, /* Finalize function. */
df_ri_free, /* Free all of the problem information. */ df_ri_free, /* Free all of the problem information. */
df_ri_dump, /* Debugging. */ df_ri_dump, /* Debugging. */
&problem_UR /* Dependent problem. */
/* Technically this is only dependent on the live registers problem
but it will produce infomation if built one of uninitialized
register problems (UR, UREC) is also run. */
df_lr_add_problem, /* Dependent problem. */
0 /* Changeable flags. */
}; };
...@@ -3242,20 +3755,7 @@ static struct df_problem problem_RI = ...@@ -3242,20 +3755,7 @@ static struct df_problem problem_RI =
solution. */ solution. */
struct dataflow * struct dataflow *
df_ri_add_problem (struct df *df) df_ri_add_problem (struct df *df, int flags)
{ {
return df_add_problem (df, &problem_RI); return df_add_problem (df, &problem_RI, flags);
} }
/* Return total lifetime (in insns) of REG. */
int
df_reg_lifetime (struct df *df, rtx reg)
{
struct dataflow *dflow = df->problems_by_index[DF_RI];
struct df_ri_problem_data *problem_data =
(struct df_ri_problem_data *) dflow->problem_data;
return problem_data->lifetime[REGNO (reg)];
}
...@@ -65,9 +65,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -65,9 +65,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#define EPILOGUE_USES(REGNO) 0 #define EPILOGUE_USES(REGNO) 0
#endif #endif
/* Indicates where we are in the compilation. */
int df_state;
/* The bitmap_obstack is used to hold some static variables that /* The bitmap_obstack is used to hold some static variables that
should not be reset after each function is compiled. */ should not be reset after each function is compiled. */
...@@ -122,6 +119,8 @@ struct df_scan_problem_data ...@@ -122,6 +119,8 @@ struct df_scan_problem_data
alloc_pool ref_pool; alloc_pool ref_pool;
alloc_pool insn_pool; alloc_pool insn_pool;
alloc_pool reg_pool; alloc_pool reg_pool;
alloc_pool mw_reg_pool;
alloc_pool mw_link_pool;
}; };
typedef struct df_scan_bb_info *df_scan_bb_info_t; typedef struct df_scan_bb_info *df_scan_bb_info_t;
...@@ -130,8 +129,8 @@ static void ...@@ -130,8 +129,8 @@ static void
df_scan_free_internal (struct dataflow *dflow) df_scan_free_internal (struct dataflow *dflow)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_scan_problem_data *problem_data = struct df_scan_problem_data *problem_data
(struct df_scan_problem_data *) dflow->problem_data; = (struct df_scan_problem_data *) dflow->problem_data;
free (df->def_info.regs); free (df->def_info.regs);
free (df->def_info.refs); free (df->def_info.refs);
...@@ -157,6 +156,8 @@ df_scan_free_internal (struct dataflow *dflow) ...@@ -157,6 +156,8 @@ df_scan_free_internal (struct dataflow *dflow)
free_alloc_pool (problem_data->ref_pool); free_alloc_pool (problem_data->ref_pool);
free_alloc_pool (problem_data->insn_pool); free_alloc_pool (problem_data->insn_pool);
free_alloc_pool (problem_data->reg_pool); free_alloc_pool (problem_data->reg_pool);
free_alloc_pool (problem_data->mw_reg_pool);
free_alloc_pool (problem_data->mw_link_pool);
} }
...@@ -200,7 +201,8 @@ df_scan_free_bb_info (struct dataflow *dflow, basic_block bb, void *vbb_info) ...@@ -200,7 +201,8 @@ df_scan_free_bb_info (struct dataflow *dflow, basic_block bb, void *vbb_info)
be rescanned. */ be rescanned. */
static void static void
df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan,
bitmap all_blocks ATTRIBUTE_UNUSED)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_scan_problem_data *problem_data; struct df_scan_problem_data *problem_data;
...@@ -231,6 +233,12 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan) ...@@ -231,6 +233,12 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
problem_data->reg_pool problem_data->reg_pool
= create_alloc_pool ("df_scan_reg pool", = create_alloc_pool ("df_scan_reg pool",
sizeof (struct df_reg_info), block_size); sizeof (struct df_reg_info), block_size);
problem_data->mw_reg_pool
= create_alloc_pool ("df_scan_mw_reg pool",
sizeof (struct df_mw_hardreg), block_size);
problem_data->mw_link_pool
= create_alloc_pool ("df_scan_mw_link pool",
sizeof (struct df_link), block_size);
insn_num += insn_num / 4; insn_num += insn_num / 4;
df_grow_reg_info (dflow, &df->def_info); df_grow_reg_info (dflow, &df->def_info);
...@@ -319,7 +327,8 @@ static struct df_problem problem_SCAN = ...@@ -319,7 +327,8 @@ static struct df_problem problem_SCAN =
NULL, /* Finalize function. */ NULL, /* Finalize function. */
df_scan_free, /* Free all of the problem information. */ df_scan_free, /* Free all of the problem information. */
df_scan_dump, /* Debugging. */ df_scan_dump, /* Debugging. */
NULL /* Dependent problem. */ NULL, /* Dependent problem. */
0 /* Changeable flags. */
}; };
...@@ -328,9 +337,9 @@ static struct df_problem problem_SCAN = ...@@ -328,9 +337,9 @@ static struct df_problem problem_SCAN =
solution. */ solution. */
struct dataflow * struct dataflow *
df_scan_add_problem (struct df *df) df_scan_add_problem (struct df *df, int flags)
{ {
return df_add_problem (df, &problem_SCAN); return df_add_problem (df, &problem_SCAN, flags);
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
...@@ -350,8 +359,8 @@ df_grow_reg_info (struct dataflow *dflow, struct df_ref_info *ref_info) ...@@ -350,8 +359,8 @@ df_grow_reg_info (struct dataflow *dflow, struct df_ref_info *ref_info)
{ {
unsigned int max_reg = max_reg_num (); unsigned int max_reg = max_reg_num ();
unsigned int new_size = max_reg; unsigned int new_size = max_reg;
struct df_scan_problem_data *problem_data = struct df_scan_problem_data *problem_data
(struct df_scan_problem_data *) dflow->problem_data; = (struct df_scan_problem_data *) dflow->problem_data;
unsigned int i; unsigned int i;
if (ref_info->regs_size < new_size) if (ref_info->regs_size < new_size)
...@@ -432,6 +441,9 @@ df_rescan_blocks (struct df *df, bitmap blocks) ...@@ -432,6 +441,9 @@ df_rescan_blocks (struct df *df, bitmap blocks)
if (blocks) if (blocks)
{ {
int i; int i;
unsigned int bb_index;
bitmap_iterator bi;
bool cleared_bits = false;
/* Need to assure that there are space in all of the tables. */ /* Need to assure that there are space in all of the tables. */
unsigned int insn_num = get_max_uid () + 1; unsigned int insn_num = get_max_uid () + 1;
...@@ -447,6 +459,20 @@ df_rescan_blocks (struct df *df, bitmap blocks) ...@@ -447,6 +459,20 @@ df_rescan_blocks (struct df *df, bitmap blocks)
df_grow_bb_info (dflow); df_grow_bb_info (dflow);
bitmap_copy (local_blocks_to_scan, blocks); bitmap_copy (local_blocks_to_scan, blocks);
EXECUTE_IF_SET_IN_BITMAP (blocks, 0, bb_index, bi)
{
basic_block bb = BASIC_BLOCK (bb_index);
if (!bb)
{
bitmap_clear_bit (local_blocks_to_scan, bb_index);
cleared_bits = true;
}
}
if (cleared_bits)
bitmap_copy (blocks, local_blocks_to_scan);
df->def_info.add_refs_inline = true; df->def_info.add_refs_inline = true;
df->use_info.add_refs_inline = true; df->use_info.add_refs_inline = true;
...@@ -490,7 +516,7 @@ df_rescan_blocks (struct df *df, bitmap blocks) ...@@ -490,7 +516,7 @@ df_rescan_blocks (struct df *df, bitmap blocks)
{ {
bitmap_set_bit (local_blocks_to_scan, bb->index); bitmap_set_bit (local_blocks_to_scan, bb->index);
} }
df_scan_alloc (dflow, local_blocks_to_scan); df_scan_alloc (dflow, local_blocks_to_scan, NULL);
df->def_info.add_refs_inline = false; df->def_info.add_refs_inline = false;
df->use_info.add_refs_inline = false; df->use_info.add_refs_inline = false;
...@@ -508,6 +534,7 @@ df_rescan_blocks (struct df *df, bitmap blocks) ...@@ -508,6 +534,7 @@ df_rescan_blocks (struct df *df, bitmap blocks)
BITMAP_FREE (local_blocks_to_scan); BITMAP_FREE (local_blocks_to_scan);
} }
/* Create a new ref of type DF_REF_TYPE for register REG at address /* Create a new ref of type DF_REF_TYPE for register REG at address
LOC within INSN of BB. */ LOC within INSN of BB. */
...@@ -634,8 +661,8 @@ df_reg_chain_unlink (struct dataflow *dflow, struct df_ref *ref) ...@@ -634,8 +661,8 @@ df_reg_chain_unlink (struct dataflow *dflow, struct df_ref *ref)
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_ref *next = DF_REF_NEXT_REG (ref); struct df_ref *next = DF_REF_NEXT_REG (ref);
struct df_ref *prev = DF_REF_PREV_REG (ref); struct df_ref *prev = DF_REF_PREV_REG (ref);
struct df_scan_problem_data *problem_data = struct df_scan_problem_data *problem_data
(struct df_scan_problem_data *) dflow->problem_data; = (struct df_scan_problem_data *) dflow->problem_data;
struct df_reg_info *reg_info; struct df_reg_info *reg_info;
struct df_ref *next_ref = ref->next_ref; struct df_ref *next_ref = ref->next_ref;
unsigned int id = DF_REF_ID (ref); unsigned int id = DF_REF_ID (ref);
...@@ -697,8 +724,8 @@ df_ref_remove (struct df *df, struct df_ref *ref) ...@@ -697,8 +724,8 @@ df_ref_remove (struct df *df, struct df_ref *ref)
= df_ref_unlink (bb_info->artificial_defs, ref); = df_ref_unlink (bb_info->artificial_defs, ref);
} }
else else
DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)) = DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref))
df_ref_unlink (DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)), ref); = df_ref_unlink (DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)), ref);
if (df->def_info.add_refs_inline) if (df->def_info.add_refs_inline)
DF_DEFS_SET (df, DF_REF_ID (ref), NULL); DF_DEFS_SET (df, DF_REF_ID (ref), NULL);
...@@ -713,8 +740,8 @@ df_ref_remove (struct df *df, struct df_ref *ref) ...@@ -713,8 +740,8 @@ df_ref_remove (struct df *df, struct df_ref *ref)
= df_ref_unlink (bb_info->artificial_uses, ref); = df_ref_unlink (bb_info->artificial_uses, ref);
} }
else else
DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)) = DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref))
df_ref_unlink (DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)), ref); = df_ref_unlink (DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)), ref);
if (df->use_info.add_refs_inline) if (df->use_info.add_refs_inline)
DF_USES_SET (df, DF_REF_ID (ref), NULL); DF_USES_SET (df, DF_REF_ID (ref), NULL);
...@@ -730,8 +757,8 @@ static struct df_insn_info * ...@@ -730,8 +757,8 @@ static struct df_insn_info *
df_insn_create_insn_record (struct dataflow *dflow, rtx insn) df_insn_create_insn_record (struct dataflow *dflow, rtx insn)
{ {
struct df *df = dflow->df; struct df *df = dflow->df;
struct df_scan_problem_data *problem_data = struct df_scan_problem_data *problem_data
(struct df_scan_problem_data *) dflow->problem_data; = (struct df_scan_problem_data *) dflow->problem_data;
struct df_insn_info *insn_rec = DF_INSN_GET (df, insn); struct df_insn_info *insn_rec = DF_INSN_GET (df, insn);
if (!insn_rec) if (!insn_rec)
...@@ -754,14 +781,31 @@ df_insn_refs_delete (struct dataflow *dflow, rtx insn) ...@@ -754,14 +781,31 @@ df_insn_refs_delete (struct dataflow *dflow, rtx insn)
unsigned int uid = INSN_UID (insn); unsigned int uid = INSN_UID (insn);
struct df_insn_info *insn_info = NULL; struct df_insn_info *insn_info = NULL;
struct df_ref *ref; struct df_ref *ref;
struct df_scan_problem_data *problem_data = struct df_scan_problem_data *problem_data
(struct df_scan_problem_data *) dflow->problem_data; = (struct df_scan_problem_data *) dflow->problem_data;
if (uid < df->insns_size) if (uid < df->insns_size)
insn_info = DF_INSN_UID_GET (df, uid); insn_info = DF_INSN_UID_GET (df, uid);
if (insn_info) if (insn_info)
{ {
struct df_mw_hardreg *hardregs = insn_info->mw_hardregs;
while (hardregs)
{
struct df_mw_hardreg *next_hr = hardregs->next;
struct df_link *link = hardregs->regs;
while (link)
{
struct df_link *next_l = link->next;
pool_free (problem_data->mw_link_pool, link);
link = next_l;
}
pool_free (problem_data->mw_reg_pool, hardregs);
hardregs = next_hr;
}
ref = insn_info->defs; ref = insn_info->defs;
while (ref) while (ref)
ref = df_reg_chain_unlink (dflow, ref); ref = df_reg_chain_unlink (dflow, ref);
...@@ -876,20 +920,6 @@ df_reorganize_refs (struct df_ref_info *ref_info) ...@@ -876,20 +920,6 @@ df_reorganize_refs (struct df_ref_info *ref_info)
} }
/* Local miscellaneous routines. */
/* Local routines for recording refs. */
/* Set where we are in the compilation. */
void
df_set_state (int state)
{
df_state = state;
}
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
Hard core instruction scanning code. No external interfaces here, Hard core instruction scanning code. No external interfaces here,
just a lot of routines that look inside insns. just a lot of routines that look inside insns.
...@@ -906,8 +936,8 @@ df_ref_create_structure (struct dataflow *dflow, rtx reg, rtx *loc, ...@@ -906,8 +936,8 @@ df_ref_create_structure (struct dataflow *dflow, rtx reg, rtx *loc,
struct df_ref *this_ref; struct df_ref *this_ref;
struct df *df = dflow->df; struct df *df = dflow->df;
int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg); int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
struct df_scan_problem_data *problem_data = struct df_scan_problem_data *problem_data
(struct df_scan_problem_data *) dflow->problem_data; = (struct df_scan_problem_data *) dflow->problem_data;
this_ref = pool_alloc (problem_data->ref_pool); this_ref = pool_alloc (problem_data->ref_pool);
DF_REF_REG (this_ref) = reg; DF_REF_REG (this_ref) = reg;
...@@ -922,76 +952,88 @@ df_ref_create_structure (struct dataflow *dflow, rtx reg, rtx *loc, ...@@ -922,76 +952,88 @@ df_ref_create_structure (struct dataflow *dflow, rtx reg, rtx *loc,
/* Link the ref into the reg_def and reg_use chains and keep a count /* Link the ref into the reg_def and reg_use chains and keep a count
of the instances. */ of the instances. */
if (ref_type == DF_REF_REG_DEF) switch (ref_type)
{ {
struct df_reg_info *reg_info = DF_REG_DEF_GET (df, regno); case DF_REF_REG_DEF:
reg_info->n_refs++; {
struct df_reg_info *reg_info = DF_REG_DEF_GET (df, regno);
/* Add the ref to the reg_def chain. */ reg_info->n_refs++;
df_reg_chain_create (reg_info, this_ref);
DF_REF_ID (this_ref) = df->def_info.bitmap_size; /* Add the ref to the reg_def chain. */
if (df->def_info.add_refs_inline) df_reg_chain_create (reg_info, this_ref);
{ DF_REF_ID (this_ref) = df->def_info.bitmap_size;
if (DF_DEFS_SIZE (df) >= df->def_info.refs_size) if (df->def_info.add_refs_inline)
{ {
int new_size = df->def_info.bitmap_size if (DF_DEFS_SIZE (df) >= df->def_info.refs_size)
+ df->def_info.bitmap_size / 4; {
df_grow_ref_info (&df->def_info, new_size); int new_size = df->def_info.bitmap_size
} + df->def_info.bitmap_size / 4;
/* Add the ref to the big array of defs. */ df_grow_ref_info (&df->def_info, new_size);
DF_DEFS_SET (df, df->def_info.bitmap_size, this_ref); }
df->def_info.refs_organized = false; /* Add the ref to the big array of defs. */
} DF_DEFS_SET (df, df->def_info.bitmap_size, this_ref);
df->def_info.refs_organized = false;
df->def_info.bitmap_size++; }
df->def_info.bitmap_size++;
if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL)
{
struct df_scan_bb_info *bb_info
= df_scan_get_bb_info (dflow, bb->index);
this_ref->next_ref = bb_info->artificial_defs;
bb_info->artificial_defs = this_ref;
}
else
{
this_ref->next_ref = DF_INSN_GET (df, insn)->defs;
DF_INSN_GET (df, insn)->defs = this_ref;
}
}
break;
if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL) case DF_REF_REG_MEM_LOAD:
{ case DF_REF_REG_MEM_STORE:
struct df_scan_bb_info *bb_info case DF_REF_REG_USE:
= df_scan_get_bb_info (dflow, bb->index); {
this_ref->next_ref = bb_info->artificial_defs; struct df_reg_info *reg_info = DF_REG_USE_GET (df, regno);
bb_info->artificial_defs = this_ref; reg_info->n_refs++;
}
else /* Add the ref to the reg_use chain. */
{ df_reg_chain_create (reg_info, this_ref);
this_ref->next_ref = DF_INSN_GET (df, insn)->defs; DF_REF_ID (this_ref) = df->use_info.bitmap_size;
DF_INSN_GET (df, insn)->defs = this_ref; if (df->use_info.add_refs_inline)
} {
} if (DF_USES_SIZE (df) >= df->use_info.refs_size)
else {
{ int new_size = df->use_info.bitmap_size
struct df_reg_info *reg_info = DF_REG_USE_GET (df, regno); + df->use_info.bitmap_size / 4;
reg_info->n_refs++; df_grow_ref_info (&df->use_info, new_size);
}
/* Add the ref to the big array of defs. */
DF_USES_SET (df, df->use_info.bitmap_size, this_ref);
df->use_info.refs_organized = false;
}
df->use_info.bitmap_size++;
if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL)
{
struct df_scan_bb_info *bb_info
= df_scan_get_bb_info (dflow, bb->index);
this_ref->next_ref = bb_info->artificial_uses;
bb_info->artificial_uses = this_ref;
}
else
{
this_ref->next_ref = DF_INSN_GET (df, insn)->uses;
DF_INSN_GET (df, insn)->uses = this_ref;
}
}
break;
/* Add the ref to the reg_use chain. */ default:
df_reg_chain_create (reg_info, this_ref); gcc_unreachable ();
DF_REF_ID (this_ref) = df->use_info.bitmap_size;
if (df->use_info.add_refs_inline)
{
if (DF_USES_SIZE (df) >= df->use_info.refs_size)
{
int new_size = df->use_info.bitmap_size
+ df->use_info.bitmap_size / 4;
df_grow_ref_info (&df->use_info, new_size);
}
/* Add the ref to the big array of defs. */
DF_USES_SET (df, df->use_info.bitmap_size, this_ref);
df->use_info.refs_organized = false;
}
df->use_info.bitmap_size++;
if (DF_REF_FLAGS (this_ref) & DF_REF_ARTIFICIAL)
{
struct df_scan_bb_info *bb_info
= df_scan_get_bb_info (dflow, bb->index);
this_ref->next_ref = bb_info->artificial_uses;
bb_info->artificial_uses = this_ref;
}
else
{
this_ref->next_ref = DF_INSN_GET (df, insn)->uses;
DF_INSN_GET (df, insn)->uses = this_ref;
}
} }
return this_ref; return this_ref;
} }
...@@ -1007,8 +1049,9 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, ...@@ -1007,8 +1049,9 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
enum df_ref_flags ref_flags, enum df_ref_flags ref_flags,
bool record_live) bool record_live)
{ {
unsigned int regno;
struct df *df = dflow->df; struct df *df = dflow->df;
rtx oldreg = reg;
unsigned int regno;
gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG); gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
...@@ -1017,7 +1060,7 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, ...@@ -1017,7 +1060,7 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
reg. As written in the docu those should have the form reg. As written in the docu those should have the form
(subreg:SI (reg:M A) N), with size(SImode) > size(Mmode). (subreg:SI (reg:M A) N), with size(SImode) > size(Mmode).
XXX Is that true? We could also use the global word_mode variable. */ XXX Is that true? We could also use the global word_mode variable. */
if ((df->flags & DF_SUBREGS) == 0 if ((dflow->flags & DF_SUBREGS) == 0
&& GET_CODE (reg) == SUBREG && GET_CODE (reg) == SUBREG
&& (GET_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (word_mode) && (GET_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (word_mode)
|| GET_MODE_SIZE (GET_MODE (reg)) || GET_MODE_SIZE (GET_MODE (reg))
...@@ -1031,10 +1074,13 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, ...@@ -1031,10 +1074,13 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg); regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
if (regno < FIRST_PSEUDO_REGISTER) if (regno < FIRST_PSEUDO_REGISTER)
{ {
int i; unsigned int i;
int endregno; unsigned int endregno;
struct df_mw_hardreg *hardreg = NULL;
struct df_scan_problem_data *problem_data
= (struct df_scan_problem_data *) dflow->problem_data;
if (! (df->flags & DF_HARD_REGS)) if (!(dflow->flags & DF_HARD_REGS))
return; return;
/* GET_MODE (reg) is correct here. We do not want to go into a SUBREG /* GET_MODE (reg) is correct here. We do not want to go into a SUBREG
...@@ -1048,8 +1094,30 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, ...@@ -1048,8 +1094,30 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
SUBREG_BYTE (reg), GET_MODE (reg)); SUBREG_BYTE (reg), GET_MODE (reg));
endregno += regno; endregno += regno;
/* If this is a multiword hardreg, we create some extra datastructures that
will enable us to easily build REG_DEAD and REG_UNUSED notes. */
if ((endregno != regno + 1) && insn)
{
struct df_insn_info *insn_info = DF_INSN_GET (df, insn);
/* Sets to a subreg of a multiword register are partial.
Sets to a non-subreg of a multiword register are not. */
if (GET_CODE (oldreg) == SUBREG)
ref_flags |= DF_REF_PARTIAL;
ref_flags |= DF_REF_MW_HARDREG;
hardreg = pool_alloc (problem_data->mw_reg_pool);
hardreg->next = insn_info->mw_hardregs;
insn_info->mw_hardregs = hardreg;
hardreg->type = ref_type;
hardreg->flags = ref_flags;
hardreg->mw_reg = reg;
hardreg->regs = NULL;
}
for (i = regno; i < endregno; i++) for (i = regno; i < endregno; i++)
{ {
struct df_ref *ref;
/* Calls are handled at call site because regs_ever_live /* Calls are handled at call site because regs_ever_live
doesn't include clobbered regs, only used ones. */ doesn't include clobbered regs, only used ones. */
if (ref_type == DF_REF_REG_DEF && record_live) if (ref_type == DF_REF_REG_DEF && record_live)
...@@ -1061,14 +1129,22 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc, ...@@ -1061,14 +1129,22 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
{ {
/* Set regs_ever_live on uses of non-eliminable frame /* Set regs_ever_live on uses of non-eliminable frame
pointers and arg pointers. */ pointers and arg pointers. */
if (! (TEST_HARD_REG_BIT (elim_reg_set, regno) if (!(TEST_HARD_REG_BIT (elim_reg_set, regno)
&& (regno == FRAME_POINTER_REGNUM && (regno == FRAME_POINTER_REGNUM
|| regno == ARG_POINTER_REGNUM))) || regno == ARG_POINTER_REGNUM)))
regs_ever_live[i] = 1; regs_ever_live[i] = 1;
} }
df_ref_create_structure (dflow, regno_reg_rtx[i], loc, ref = df_ref_create_structure (dflow, regno_reg_rtx[i], loc,
bb, insn, ref_type, ref_flags); bb, insn, ref_type, ref_flags);
if (hardreg)
{
struct df_link *link = pool_alloc (problem_data->mw_link_pool);
link->next = hardreg->regs;
link->ref = ref;
hardreg->regs = link;
}
} }
} }
else else
...@@ -1107,6 +1183,7 @@ df_def_record_1 (struct dataflow *dflow, rtx x, ...@@ -1107,6 +1183,7 @@ df_def_record_1 (struct dataflow *dflow, rtx x,
{ {
rtx *loc; rtx *loc;
rtx dst; rtx dst;
bool dst_in_strict_lowpart = false;
/* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL /* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
construct. */ construct. */
...@@ -1127,7 +1204,8 @@ df_def_record_1 (struct dataflow *dflow, rtx x, ...@@ -1127,7 +1204,8 @@ df_def_record_1 (struct dataflow *dflow, rtx x,
if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER
|| GET_CODE (temp) == SET) || GET_CODE (temp) == SET)
df_def_record_1 (dflow, temp, bb, insn, df_def_record_1 (dflow, temp, bb, insn,
GET_CODE (temp) == CLOBBER ? flags | DF_REF_CLOBBER : flags, GET_CODE (temp) == CLOBBER
? flags | DF_REF_MUST_CLOBBER : flags,
record_live); record_live);
} }
return; return;
...@@ -1149,10 +1227,20 @@ df_def_record_1 (struct dataflow *dflow, rtx x, ...@@ -1149,10 +1227,20 @@ df_def_record_1 (struct dataflow *dflow, rtx x,
} }
#endif #endif
loc = &XEXP (dst, 0); loc = &XEXP (dst, 0);
if (GET_CODE (dst) == STRICT_LOW_PART)
dst_in_strict_lowpart = true;
dst = *loc; dst = *loc;
flags |= DF_REF_READ_WRITE; flags |= DF_REF_READ_WRITE;
} }
/* Sets to a subreg of a single word register are partial sets if
they are wrapped in a strict lowpart, and not partial otherwise.
*/
if (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst))
&& dst_in_strict_lowpart)
flags |= DF_REF_PARTIAL;
if (REG_P (dst) if (REG_P (dst)
|| (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst)))) || (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst))))
df_ref_record (dflow, dst, loc, bb, insn, df_ref_record (dflow, dst, loc, bb, insn,
...@@ -1171,7 +1259,7 @@ df_defs_record (struct dataflow *dflow, rtx x, basic_block bb, rtx insn) ...@@ -1171,7 +1259,7 @@ df_defs_record (struct dataflow *dflow, rtx x, basic_block bb, rtx insn)
{ {
/* Mark the single def within the pattern. */ /* Mark the single def within the pattern. */
df_def_record_1 (dflow, x, bb, insn, df_def_record_1 (dflow, x, bb, insn,
code == CLOBBER ? DF_REF_CLOBBER : 0, true); code == CLOBBER ? DF_REF_MUST_CLOBBER : 0, true);
} }
else if (code == COND_EXEC) else if (code == COND_EXEC)
{ {
...@@ -1232,7 +1320,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type, ...@@ -1232,7 +1320,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
case SUBREG: case SUBREG:
/* While we're here, optimize this case. */ /* While we're here, optimize this case. */
flags |= DF_REF_PARTIAL;
/* In case the SUBREG is not of a REG, do not optimize. */ /* In case the SUBREG is not of a REG, do not optimize. */
if (!REG_P (SUBREG_REG (x))) if (!REG_P (SUBREG_REG (x)))
{ {
...@@ -1424,8 +1512,8 @@ df_insn_contains_asm (rtx insn) ...@@ -1424,8 +1512,8 @@ df_insn_contains_asm (rtx insn)
static void static void
df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
{ {
int i;
struct df *df = dflow->df; struct df *df = dflow->df;
int i;
if (INSN_P (insn)) if (INSN_P (insn))
{ {
...@@ -1437,7 +1525,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) ...@@ -1437,7 +1525,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
/* Record register defs. */ /* Record register defs. */
df_defs_record (dflow, PATTERN (insn), bb, insn); df_defs_record (dflow, PATTERN (insn), bb, insn);
if (df->flags & DF_EQUIV_NOTES) if (dflow->flags & DF_EQUIV_NOTES)
for (note = REG_NOTES (insn); note; for (note = REG_NOTES (insn); note;
note = XEXP (note, 1)) note = XEXP (note, 1))
{ {
...@@ -1490,7 +1578,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) ...@@ -1490,7 +1578,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
DF_REF_REG_USE, bb, insn, DF_REF_REG_USE, bb, insn,
0); 0);
if (df->flags & DF_HARD_REGS) if (dflow->flags & DF_HARD_REGS)
{ {
bitmap_iterator bi; bitmap_iterator bi;
unsigned int ui; unsigned int ui;
...@@ -1502,8 +1590,8 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn) ...@@ -1502,8 +1590,8 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
DF_REF_REG_USE, bb, insn, DF_REF_REG_USE, bb, insn,
0); 0);
EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi) EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi)
df_ref_record (dflow, regno_reg_rtx[ui], &regno_reg_rtx[ui], bb, insn, df_ref_record (dflow, regno_reg_rtx[ui], &regno_reg_rtx[ui], bb,
DF_REF_REG_DEF, DF_REF_CLOBBER, false); insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER, false);
} }
} }
...@@ -1537,6 +1625,10 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) ...@@ -1537,6 +1625,10 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
rtx insn; rtx insn;
int luid = 0; int luid = 0;
struct df_scan_bb_info *bb_info = df_scan_get_bb_info (dflow, bb->index); struct df_scan_bb_info *bb_info = df_scan_get_bb_info (dflow, bb->index);
bitmap artificial_uses_at_bottom = NULL;
if (dflow->flags & DF_HARD_REGS)
artificial_uses_at_bottom = BITMAP_ALLOC (NULL);
/* Need to make sure that there is a record in the basic block info. */ /* Need to make sure that there is a record in the basic block info. */
if (!bb_info) if (!bb_info)
...@@ -1561,7 +1653,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) ...@@ -1561,7 +1653,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
} }
#ifdef EH_RETURN_DATA_REGNO #ifdef EH_RETURN_DATA_REGNO
if ((df->flags & DF_HARD_REGS) if ((dflow->flags & DF_HARD_REGS)
&& df_has_eh_preds (bb)) && df_has_eh_preds (bb))
{ {
unsigned int i; unsigned int i;
...@@ -1580,7 +1672,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) ...@@ -1580,7 +1672,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
#endif #endif
if ((df->flags & DF_HARD_REGS) if ((dflow->flags & DF_HARD_REGS)
&& df_has_eh_preds (bb)) && df_has_eh_preds (bb))
{ {
#ifdef EH_USES #ifdef EH_USES
...@@ -1611,56 +1703,60 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb) ...@@ -1611,56 +1703,60 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
{ {
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
df_uses_record (dflow, &regno_reg_rtx[FRAME_POINTER_REGNUM], bitmap_set_bit (artificial_uses_at_bottom, FRAME_POINTER_REGNUM);
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
df_uses_record (dflow, &regno_reg_rtx[HARD_FRAME_POINTER_REGNUM], bitmap_set_bit (artificial_uses_at_bottom, HARD_FRAME_POINTER_REGNUM);
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
#endif #endif
} }
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
if (fixed_regs[ARG_POINTER_REGNUM]) if (fixed_regs[ARG_POINTER_REGNUM])
df_uses_record (dflow, &regno_reg_rtx[ARG_POINTER_REGNUM], bitmap_set_bit (artificial_uses_at_bottom, ARG_POINTER_REGNUM);
DF_REF_REG_USE, bb, NULL,
DF_REF_ARTIFICIAL);
#endif #endif
} }
} }
if ((df->flags & DF_HARD_REGS) if ((dflow->flags & DF_HARD_REGS)
&& bb->index >= NUM_FIXED_BLOCKS) && bb->index >= NUM_FIXED_BLOCKS)
{ {
/* Before reload, there are a few registers that must be forced /* Before reload, there are a few registers that must be forced
live everywhere -- which might not already be the case for live everywhere -- which might not already be the case for
blocks within infinite loops. */ blocks within infinite loops. */
if (! reload_completed) if (!reload_completed)
{ {
/* Any reference to any pseudo before reload is a potential /* Any reference to any pseudo before reload is a potential
reference of the frame pointer. */ reference of the frame pointer. */
df_uses_record (dflow, &regno_reg_rtx[FRAME_POINTER_REGNUM], bitmap_set_bit (artificial_uses_at_bottom, FRAME_POINTER_REGNUM);
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* Pseudos with argument area equivalences may require /* Pseudos with argument area equivalences may require
reloading via the argument pointer. */ reloading via the argument pointer. */
if (fixed_regs[ARG_POINTER_REGNUM]) if (fixed_regs[ARG_POINTER_REGNUM])
df_uses_record (dflow, &regno_reg_rtx[ARG_POINTER_REGNUM], bitmap_set_bit (artificial_uses_at_bottom, ARG_POINTER_REGNUM);
DF_REF_REG_USE, bb, NULL,
DF_REF_ARTIFICIAL);
#endif #endif
/* Any constant, or pseudo with constant equivalences, may /* Any constant, or pseudo with constant equivalences, may
require reloading from memory using the pic register. */ require reloading from memory using the pic register. */
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
&& fixed_regs[PIC_OFFSET_TABLE_REGNUM]) && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
df_uses_record (dflow, &regno_reg_rtx[PIC_OFFSET_TABLE_REGNUM], bitmap_set_bit (artificial_uses_at_bottom, PIC_OFFSET_TABLE_REGNUM);
DF_REF_REG_USE, bb, NULL,
DF_REF_ARTIFICIAL);
} }
/* The all-important stack pointer must always be live. */ /* The all-important stack pointer must always be live. */
df_uses_record (dflow, &regno_reg_rtx[STACK_POINTER_REGNUM], bitmap_set_bit (artificial_uses_at_bottom, STACK_POINTER_REGNUM);
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL); }
if (dflow->flags & DF_HARD_REGS)
{
bitmap_iterator bi;
unsigned int regno;
EXECUTE_IF_SET_IN_BITMAP (artificial_uses_at_bottom, 0, regno, bi)
{
df_uses_record (dflow, &regno_reg_rtx[regno],
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
}
BITMAP_FREE (artificial_uses_at_bottom);
} }
} }
...@@ -1716,16 +1812,16 @@ df_mark_reg (rtx reg, void *vset) ...@@ -1716,16 +1812,16 @@ df_mark_reg (rtx reg, void *vset)
entry to the function. */ entry to the function. */
static void static void
df_record_entry_block_defs (struct dataflow * dflow) df_record_entry_block_defs (struct dataflow *dflow)
{ {
unsigned int i; unsigned int i;
bitmap_iterator bi; bitmap_iterator bi;
rtx r; rtx r;
struct df * df = dflow->df; struct df *df = dflow->df;
bitmap_clear (df->entry_block_defs); bitmap_clear (df->entry_block_defs);
if (! (df->flags & DF_HARD_REGS)) if (!(dflow->flags & DF_HARD_REGS))
return; return;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
...@@ -1750,6 +1846,9 @@ df_record_entry_block_defs (struct dataflow * dflow) ...@@ -1750,6 +1846,9 @@ df_record_entry_block_defs (struct dataflow * dflow)
} }
else else
{ {
/* The always important stack pointer. */
bitmap_set_bit (df->entry_block_defs, STACK_POINTER_REGNUM);
#ifdef INCOMING_RETURN_ADDR_RTX #ifdef INCOMING_RETURN_ADDR_RTX
if (REG_P (INCOMING_RETURN_ADDR_RTX)) if (REG_P (INCOMING_RETURN_ADDR_RTX))
bitmap_set_bit (df->entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX)); bitmap_set_bit (df->entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX));
...@@ -1771,13 +1870,21 @@ df_record_entry_block_defs (struct dataflow * dflow) ...@@ -1771,13 +1870,21 @@ df_record_entry_block_defs (struct dataflow * dflow)
bitmap_set_bit (df->entry_block_defs, REGNO (r)); bitmap_set_bit (df->entry_block_defs, REGNO (r));
} }
/* These registers are live everywhere. */ if ((!reload_completed) || frame_pointer_needed)
if (!reload_completed)
{ {
/* Any reference to any pseudo before reload is a potential /* Any reference to any pseudo before reload is a potential
reference of the frame pointer. */ reference of the frame pointer. */
bitmap_set_bit (df->entry_block_defs, FRAME_POINTER_REGNUM); bitmap_set_bit (df->entry_block_defs, FRAME_POINTER_REGNUM);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If they are different, also mark the hard frame pointer as live. */
if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
bitmap_set_bit (df->entry_block_defs, HARD_FRAME_POINTER_REGNUM);
#endif
}
/* These registers are live everywhere. */
if (!reload_completed)
{
#ifdef EH_USES #ifdef EH_USES
/* The ia-64, the only machine that uses this, does not define these /* The ia-64, the only machine that uses this, does not define these
until after reload. */ until after reload. */
...@@ -1826,15 +1933,15 @@ df_record_exit_block_uses (struct dataflow *dflow) ...@@ -1826,15 +1933,15 @@ df_record_exit_block_uses (struct dataflow *dflow)
bitmap_clear (df->exit_block_uses); bitmap_clear (df->exit_block_uses);
if (! (df->flags & DF_HARD_REGS)) if (!(dflow->flags & DF_HARD_REGS))
return; return;
/* If exiting needs the right stack value, consider the stack /* If exiting needs the right stack value, consider the stack
pointer live at the end of the function. */ pointer live at the end of the function. */
if ((HAVE_epilogue && epilogue_completed) if ((HAVE_epilogue && epilogue_completed)
|| ! EXIT_IGNORE_STACK || !EXIT_IGNORE_STACK
|| (! FRAME_POINTER_REQUIRED || (!FRAME_POINTER_REQUIRED
&& ! current_function_calls_alloca && !current_function_calls_alloca
&& flag_omit_frame_pointer) && flag_omit_frame_pointer)
|| current_function_sp_is_unchanging) || current_function_sp_is_unchanging)
{ {
...@@ -1845,12 +1952,12 @@ df_record_exit_block_uses (struct dataflow *dflow) ...@@ -1845,12 +1952,12 @@ df_record_exit_block_uses (struct dataflow *dflow)
If we end up eliminating it, it will be removed from the live If we end up eliminating it, it will be removed from the live
list of each basic block by reload. */ list of each basic block by reload. */
if (! reload_completed || frame_pointer_needed) if ((!reload_completed) || frame_pointer_needed)
{ {
bitmap_set_bit (df->exit_block_uses, FRAME_POINTER_REGNUM); bitmap_set_bit (df->exit_block_uses, FRAME_POINTER_REGNUM);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If they are different, also mark the hard frame pointer as live. */ /* If they are different, also mark the hard frame pointer as live. */
if (! LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM)) if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
bitmap_set_bit (df->exit_block_uses, HARD_FRAME_POINTER_REGNUM); bitmap_set_bit (df->exit_block_uses, HARD_FRAME_POINTER_REGNUM);
#endif #endif
} }
...@@ -1875,8 +1982,8 @@ df_record_exit_block_uses (struct dataflow *dflow) ...@@ -1875,8 +1982,8 @@ df_record_exit_block_uses (struct dataflow *dflow)
{ {
/* Mark all call-saved registers that we actually used. */ /* Mark all call-saved registers that we actually used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i] && ! LOCAL_REGNO (i) if (regs_ever_live[i] && !LOCAL_REGNO (i)
&& ! TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) && !TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
bitmap_set_bit (df->exit_block_uses, i); bitmap_set_bit (df->exit_block_uses, i);
} }
...@@ -1893,7 +2000,7 @@ df_record_exit_block_uses (struct dataflow *dflow) ...@@ -1893,7 +2000,7 @@ df_record_exit_block_uses (struct dataflow *dflow)
#endif #endif
#ifdef EH_RETURN_STACKADJ_RTX #ifdef EH_RETURN_STACKADJ_RTX
if ((! HAVE_epilogue || ! epilogue_completed) if ((!HAVE_epilogue || ! epilogue_completed)
&& current_function_calls_eh_return) && current_function_calls_eh_return)
{ {
rtx tmp = EH_RETURN_STACKADJ_RTX; rtx tmp = EH_RETURN_STACKADJ_RTX;
...@@ -1903,7 +2010,7 @@ df_record_exit_block_uses (struct dataflow *dflow) ...@@ -1903,7 +2010,7 @@ df_record_exit_block_uses (struct dataflow *dflow)
#endif #endif
#ifdef EH_RETURN_HANDLER_RTX #ifdef EH_RETURN_HANDLER_RTX
if ((! HAVE_epilogue || ! epilogue_completed) if ((!HAVE_epilogue || ! epilogue_completed)
&& current_function_calls_eh_return) && current_function_calls_eh_return)
{ {
rtx tmp = EH_RETURN_HANDLER_RTX; rtx tmp = EH_RETURN_HANDLER_RTX;
...@@ -1915,7 +2022,7 @@ df_record_exit_block_uses (struct dataflow *dflow) ...@@ -1915,7 +2022,7 @@ df_record_exit_block_uses (struct dataflow *dflow)
/* Mark function return value. */ /* Mark function return value. */
diddle_return_value (df_mark_reg, (void*) df->exit_block_uses); diddle_return_value (df_mark_reg, (void*) df->exit_block_uses);
if (df->flags & DF_HARD_REGS) if (dflow->flags & DF_HARD_REGS)
EXECUTE_IF_SET_IN_BITMAP (df->exit_block_uses, 0, i, bi) EXECUTE_IF_SET_IN_BITMAP (df->exit_block_uses, 0, i, bi)
df_uses_record (dflow, &regno_reg_rtx[i], df_uses_record (dflow, &regno_reg_rtx[i],
DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL, DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
......
...@@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
struct dataflow; struct dataflow;
struct df; struct df;
struct df_problem; struct df_problem;
struct df_link;
/* Data flow problems. All problems must have a unique here. */ /* Data flow problems. All problems must have a unique here. */
/* Scanning is not really a dataflow problem, but it is useful to have /* Scanning is not really a dataflow problem, but it is useful to have
...@@ -49,10 +50,6 @@ struct df_problem; ...@@ -49,10 +50,6 @@ struct df_problem;
#define DF_RI 7 /* Register Info. */ #define DF_RI 7 /* Register Info. */
#define DF_LAST_PROBLEM_PLUS1 (DF_RI + 1) #define DF_LAST_PROBLEM_PLUS1 (DF_RI + 1)
/* Flags that control the building of chains. */
#define DF_DU_CHAIN 1 /* Build DU chains. */
#define DF_UD_CHAIN 2 /* Build UD chains. */
/* Dataflow direction. */ /* Dataflow direction. */
enum df_flow_dir enum df_flow_dir
...@@ -62,10 +59,72 @@ enum df_flow_dir ...@@ -62,10 +59,72 @@ enum df_flow_dir
DF_BACKWARD DF_BACKWARD
}; };
/* The first of these is a set of a register. The remaining three are
all uses of a register (the mem_load and mem_store relate to how
the register as an addressing operand). */
enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD,
DF_REF_REG_MEM_STORE};
#define DF_REF_TYPE_NAMES {"def", "use", "mem load", "mem store"}
enum df_ref_flags
{
/* Read-modify-write refs generate both a use and a def and
these are marked with this flag to show that they are not
independent. */
DF_REF_READ_WRITE = 1,
/* This flag is set, if we stripped the subreg from the reference.
In this case we must make conservative guesses, at what the
outer mode was. */
DF_REF_STRIPPED = 2,
/* If this flag is set, this is not a real definition/use, but an
artificial one created to model always live registers, eh uses, etc. */
DF_REF_ARTIFICIAL = 4,
/* If this flag is set for an artificial use or def, that ref
logically happens at the top of the block. If it is not set
for an artificial use or def, that ref logically happens at the
bottom of the block. This is never set for regular refs. */
DF_REF_AT_TOP = 8,
/* This flag is set if the use is inside a REG_EQUAL note. */
DF_REF_IN_NOTE = 16,
/* This flag is set if this ref, generally a def, may clobber the
referenced register. This is generally only set for hard
registers that cross a call site. With better information
about calls, some of these could be changed in the future to
DF_REF_MUST_CLOBBER. */
DF_REF_MAY_CLOBBER = 32,
/* This flag is set if this ref, generally a def, is a real
clobber. This is not currently set for registers live across a
call because that clobbering may or may not happen.
Most of the uses of this are with sets that have a
GET_CODE(..)==CLOBBER. Note that this is set even if the
clobber is to a subreg. So in order to tell if the clobber
wipes out the entire register, it is necessary to also check
the DF_REF_PARTIAL flag. */
DF_REF_MUST_CLOBBER = 64,
/* This bit is true if this ref is part of a multiword hardreg. */
DF_REF_MW_HARDREG = 128,
/* This flag is set if this ref is a partial use or def of the
associated register. */
DF_REF_PARTIAL = 256
};
/* Function prototypes added to df_problem instance. */ /* Function prototypes added to df_problem instance. */
/* Allocate the problem specific data. */ /* Allocate the problem specific data. */
typedef void (*df_alloc_function) (struct dataflow *, bitmap); typedef void (*df_alloc_function) (struct dataflow *, bitmap, bitmap);
/* This function is called if the problem has global data that needs /* This function is called if the problem has global data that needs
to be cleared when ever the set of blocks changes. The bitmap to be cleared when ever the set of blocks changes. The bitmap
...@@ -107,6 +166,10 @@ typedef void (*df_free_function) (struct dataflow *); ...@@ -107,6 +166,10 @@ typedef void (*df_free_function) (struct dataflow *);
/* Function to dump results to FILE. */ /* Function to dump results to FILE. */
typedef void (*df_dump_problem_function) (struct dataflow *, FILE *); typedef void (*df_dump_problem_function) (struct dataflow *, FILE *);
/* Function to add problem a dataflow problem that must be solved
before this problem can be solved. */
typedef struct dataflow * (*df_dependent_problem_function) (struct df *, int);
/* The static description of a dataflow problem to solve. See above /* The static description of a dataflow problem to solve. See above
typedefs for doc for the function fields. */ typedefs for doc for the function fields. */
...@@ -127,10 +190,10 @@ struct df_problem { ...@@ -127,10 +190,10 @@ struct df_problem {
df_finalizer_function finalize_fun; df_finalizer_function finalize_fun;
df_free_function free_fun; df_free_function free_fun;
df_dump_problem_function dump_fun; df_dump_problem_function dump_fun;
df_dependent_problem_function dependent_problem_fun;
/* A dataflow problem that must be solved before this problem can be /* Flags can be changed after analysis starts. */
solved. */ int changeable_flags;
struct df_problem *dependent_problem;
}; };
...@@ -151,6 +214,20 @@ struct dataflow ...@@ -151,6 +214,20 @@ struct dataflow
/* The pool to allocate the block_info from. */ /* The pool to allocate the block_info from. */
alloc_pool block_pool; alloc_pool block_pool;
/* Problem specific control infomation. */
/* Scanning flags. */
#define DF_HARD_REGS 1 /* Mark hard registers. */
#define DF_EQUIV_NOTES 2 /* Mark uses present in EQUIV/EQUAL notes. */
#define DF_SUBREGS 4 /* Return subregs rather than the inner reg. */
/* Flags that control the building of chains. */
#define DF_DU_CHAIN 1 /* Build DU chains. */
#define DF_UD_CHAIN 2 /* Build UD chains. */
/* Flag to control the building of register info. */
#define DF_RI_LIFE 1 /* Build register info. */
int flags;
/* Other problem specific data that is not on a per basic block /* Other problem specific data that is not on a per basic block
basis. The structure is generally defined privately for the basis. The structure is generally defined privately for the
problem. The exception being the scanning problem where it is problem. The exception being the scanning problem where it is
...@@ -158,17 +235,35 @@ struct dataflow ...@@ -158,17 +235,35 @@ struct dataflow
void *problem_data; void *problem_data;
}; };
/* The set of multiword hardregs used as operands to this
instruction. These are factored into individual uses and defs but
the aggregate is still needed to service the REG_DEAD and
REG_UNUSED notes. */
struct df_mw_hardreg
{
rtx mw_reg; /* The multiword hardreg. */
enum df_ref_type type; /* Used to see if the ref is read or write. */
enum df_ref_flags flags; /* Various flags. */
struct df_link *regs; /* The individual regs that make up
this hardreg. */
struct df_mw_hardreg *next; /* The next mw_hardreg in this insn. */
};
/* One of these structures is allocated for every insn. */ /* One of these structures is allocated for every insn. */
struct df_insn_info struct df_insn_info
{ {
struct df_ref *defs; /* Head of insn-def chain. */ struct df_ref *defs; /* Head of insn-def chain. */
struct df_ref *uses; /* Head of insn-use chain. */ struct df_ref *uses; /* Head of insn-use chain. */
struct df_mw_hardreg *mw_hardregs;
/* ???? The following luid field should be considered private so that /* ???? The following luid field should be considered private so that
we can change it on the fly to accommodate new insns? */ we can change it on the fly to accommodate new insns? */
int luid; /* Logical UID. */ int luid; /* Logical UID. */
bool contains_asm; /* Contains an asm instruction. */ bool contains_asm; /* Contains an asm instruction. */
}; };
/* Two of these structures are allocated for every pseudo reg, one for /* Two of these structures are allocated for every pseudo reg, one for
the uses and one for the defs. */ the uses and one for the defs. */
struct df_reg_info struct df_reg_info
...@@ -178,48 +273,6 @@ struct df_reg_info ...@@ -178,48 +273,6 @@ struct df_reg_info
unsigned int n_refs; /* Number of refs or defs for this pseudo. */ unsigned int n_refs; /* Number of refs or defs for this pseudo. */
}; };
enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD,
DF_REF_REG_MEM_STORE};
#define DF_REF_TYPE_NAMES {"def", "use", "mem load", "mem store"}
enum df_ref_flags
{
/* Read-modify-write refs generate both a use and a def and
these are marked with this flag to show that they are not
independent. */
DF_REF_READ_WRITE = 1,
/* This flag is set, if we stripped the subreg from the reference.
In this case we must make conservative guesses, at what the
outer mode was. */
DF_REF_STRIPPED = 2,
/* If this flag is set, this is not a real definition/use, but an
artificial one created to model always live registers, eh uses, etc. */
DF_REF_ARTIFICIAL = 4,
/* If this flag is set for an artificial use or def, that ref
logically happens at the top of the block. If it is not set
for an artificial use or def, that ref logically happens at the
bottom of the block. This is never set for regular refs. */
DF_REF_AT_TOP = 8,
/* This flag is set if the use is inside a REG_EQUAL note. */
DF_REF_IN_NOTE = 16,
/* This flag is set if this ref is really a clobber, and not a def. */
DF_REF_CLOBBER = 32,
/* True if ref is dead (i.e. the next ref is a def or clobber or
the end of the function.) This is only valid the RI problem
has been set in this df instance. */
DF_REF_DIES_AFTER_THIS_USE = 64
};
/* Define a register reference structure. One of these is allocated /* Define a register reference structure. One of these is allocated
for every register reference (use or def). Note some register for every register reference (use or def). Note some register
references (e.g., post_inc, subreg) generate both a def and a use. */ references (e.g., post_inc, subreg) generate both a def and a use. */
...@@ -250,9 +303,9 @@ struct df_ref ...@@ -250,9 +303,9 @@ struct df_ref
void *data; /* The data assigned to it by user. */ void *data; /* The data assigned to it by user. */
}; };
/* There are two kinds of links: */ /* These links are used for two purposes:
1) def-use or use-def chains.
/* This is used for def-use or use-def chains. */ 2) Multiword hard registers that underly a single hardware register. */
struct df_link struct df_link
{ {
struct df_ref *ref; struct df_ref *ref;
...@@ -288,12 +341,6 @@ struct df_ref_info ...@@ -288,12 +341,6 @@ struct df_ref_info
struct df struct df
{ {
#define DF_HARD_REGS 1 /* Mark hard registers. */
#define DF_EQUIV_NOTES 2 /* Mark uses present in EQUIV/EQUAL notes. */
#define DF_SUBREGS 4 /* Return subregs rather than the inner reg. */
int flags; /* Indicates what's recorded. */
/* The set of problems to be solved is stored in two arrays. In /* The set of problems to be solved is stored in two arrays. In
PROBLEMS_IN_ORDER, the problems are stored in the order that they PROBLEMS_IN_ORDER, the problems are stored in the order that they
are solved. This is an internally dense array that may have are solved. This is an internally dense array that may have
...@@ -379,7 +426,7 @@ struct df ...@@ -379,7 +426,7 @@ struct df
/* Macros to determine the reference type. */ /* Macros to determine the reference type. */
#define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF) #define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF)
#define DF_REF_REG_USE_P(REF) ((REF) && ! DF_REF_REG_DEF_P (REF)) #define DF_REF_REG_USE_P(REF) ((REF) && !DF_REF_REG_DEF_P (REF))
#define DF_REF_REG_MEM_STORE_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_STORE) #define DF_REF_REG_MEM_STORE_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_STORE)
#define DF_REF_REG_MEM_LOAD_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_LOAD) #define DF_REF_REG_MEM_LOAD_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_LOAD)
#define DF_REF_REG_MEM_P(REF) (DF_REF_REG_MEM_STORE_P (REF) \ #define DF_REF_REG_MEM_P(REF) (DF_REF_REG_MEM_STORE_P (REF) \
...@@ -398,8 +445,10 @@ struct df ...@@ -398,8 +445,10 @@ struct df
#define DF_REG_SIZE(DF) ((DF)->def_info.regs_inited) #define DF_REG_SIZE(DF) ((DF)->def_info.regs_inited)
#define DF_REG_DEF_GET(DF, REG) ((DF)->def_info.regs[(REG)]) #define DF_REG_DEF_GET(DF, REG) ((DF)->def_info.regs[(REG)])
#define DF_REG_DEF_SET(DF, REG, VAL) ((DF)->def_info.regs[(REG)]=(VAL)) #define DF_REG_DEF_SET(DF, REG, VAL) ((DF)->def_info.regs[(REG)]=(VAL))
#define DF_REG_DEF_COUNT(DF, REG) ((DF)->def_info.regs[(REG)]->n_refs)
#define DF_REG_USE_GET(DF, REG) ((DF)->use_info.regs[(REG)]) #define DF_REG_USE_GET(DF, REG) ((DF)->use_info.regs[(REG)])
#define DF_REG_USE_SET(DF, REG, VAL) ((DF)->use_info.regs[(REG)]=(VAL)) #define DF_REG_USE_SET(DF, REG, VAL) ((DF)->use_info.regs[(REG)]=(VAL))
#define DF_REG_USE_COUNT(DF, REG) ((DF)->use_info.regs[(REG)]->n_refs)
/* Macros to access the elements within the reg_info structure table. */ /* Macros to access the elements within the reg_info structure table. */
...@@ -422,27 +471,13 @@ struct df ...@@ -422,27 +471,13 @@ struct df
#define DF_INSN_UID_LUID(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->luid) #define DF_INSN_UID_LUID(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->luid)
#define DF_INSN_UID_DEFS(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->defs) #define DF_INSN_UID_DEFS(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->defs)
#define DF_INSN_UID_USES(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->uses) #define DF_INSN_UID_USES(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->uses)
#define DF_INSN_UID_MWS(DF, INSN) (DF_INSN_UID_GET(DF,INSN)->mw_hardregs)
/* This is a bitmap copy of regs_invalidated_by_call so that we can /* This is a bitmap copy of regs_invalidated_by_call so that we can
easily add it into bitmaps, etc. */ easily add it into bitmaps, etc. */
extern bitmap df_invalidated_by_call; extern bitmap df_invalidated_by_call;
/* Initialize ur_in and ur_out as if all hard registers were partially
available. */
/* The way that registers are processed, especially hard registers,
changes as the compilation proceeds. These states are passed to
df_set_state to control this processing. */
#define DF_SCAN_INITIAL 1 /* Processing from beginning of rtl to
global-alloc. */
#define DF_SCAN_GLOBAL 2 /* Processing before global
allocation. */
#define DF_SCAN_POST_ALLOC 4 /* Processing after register
allocation. */
extern int df_state; /* Indicates where we are in the compilation. */
/* One of these structures is allocated for every basic block. */ /* One of these structures is allocated for every basic block. */
struct df_scan_bb_info struct df_scan_bb_info
...@@ -513,9 +548,13 @@ struct df_urec_bb_info ...@@ -513,9 +548,13 @@ struct df_urec_bb_info
/* Functions defined in df-core.c. */ /* Functions defined in df-core.c. */
extern struct df *df_init (int); extern struct df *df_init (int);
extern struct dataflow *df_add_problem (struct df *, struct df_problem *); extern struct dataflow *df_add_problem (struct df *, struct df_problem *, int);
extern int df_set_flags (struct dataflow *, int);
extern int df_clear_flags (struct dataflow *, int);
extern void df_set_blocks (struct df*, bitmap); extern void df_set_blocks (struct df*, bitmap);
extern void df_delete_basic_block (struct df *, int);
extern void df_finish1 (struct df *); extern void df_finish1 (struct df *);
extern void df_analyze_problem (struct dataflow *, bitmap, bitmap, bitmap, int *, int, bool);
extern void df_analyze (struct df *); extern void df_analyze (struct df *);
extern void df_compact_blocks (struct df *); extern void df_compact_blocks (struct df *);
extern void df_bb_replace (struct df *, int, basic_block); extern void df_bb_replace (struct df *, int, basic_block);
...@@ -529,13 +568,12 @@ extern struct df_ref *df_find_use (struct df *, rtx, rtx); ...@@ -529,13 +568,12 @@ extern struct df_ref *df_find_use (struct df *, rtx, rtx);
extern bool df_reg_used (struct df *, rtx, rtx); extern bool df_reg_used (struct df *, rtx, rtx);
extern void df_iterative_dataflow (struct dataflow *, bitmap, bitmap, int *, int, bool); extern void df_iterative_dataflow (struct dataflow *, bitmap, bitmap, int *, int, bool);
extern void df_dump (struct df *, FILE *); extern void df_dump (struct df *, FILE *);
extern void df_chain_dump (struct df *, struct df_link *, FILE *); extern void df_refs_chain_dump (struct df_ref *, bool, FILE *);
extern void df_refs_chain_dump (struct df *, struct df_ref *, bool, FILE *);
extern void df_regs_chain_dump (struct df *, struct df_ref *, FILE *); extern void df_regs_chain_dump (struct df *, struct df_ref *, FILE *);
extern void df_insn_debug (struct df *, rtx, bool, FILE *); extern void df_insn_debug (struct df *, rtx, bool, FILE *);
extern void df_insn_debug_regno (struct df *, rtx, FILE *); extern void df_insn_debug_regno (struct df *, rtx, FILE *);
extern void df_regno_debug (struct df *, unsigned int, FILE *); extern void df_regno_debug (struct df *, unsigned int, FILE *);
extern void df_ref_debug (struct df *, struct df_ref *, FILE *); extern void df_ref_debug (struct df_ref *, FILE *);
extern void debug_df_insn (rtx); extern void debug_df_insn (rtx);
extern void debug_df_regno (unsigned int); extern void debug_df_regno (unsigned int);
extern void debug_df_reg (rtx); extern void debug_df_reg (rtx);
...@@ -549,34 +587,32 @@ extern struct df *shared_df; ...@@ -549,34 +587,32 @@ extern struct df *shared_df;
/* Functions defined in df-problems.c. */ /* Functions defined in df-problems.c. */
extern struct dataflow *df_get_dependent_problem (struct dataflow *);
extern struct df_link *df_chain_create (struct dataflow *, struct df_ref *, struct df_ref *); extern struct df_link *df_chain_create (struct dataflow *, struct df_ref *, struct df_ref *);
extern void df_chain_unlink (struct dataflow *, struct df_ref *, struct df_link *); extern void df_chain_unlink (struct dataflow *, struct df_ref *, struct df_link *);
extern void df_chain_copy (struct dataflow *, struct df_ref *, struct df_link *); extern void df_chain_copy (struct dataflow *, struct df_ref *, struct df_link *);
extern bitmap df_get_live_in (struct df *, basic_block); extern bitmap df_get_live_in (struct df *, basic_block);
extern bitmap df_get_live_out (struct df *, basic_block); extern bitmap df_get_live_out (struct df *, basic_block);
extern void df_grow_bb_info (struct dataflow *); extern void df_grow_bb_info (struct dataflow *);
extern void df_chain_dump (struct df *, struct df_link *, FILE *); extern void df_chain_dump (struct df_link *, FILE *);
extern void df_print_bb_index (basic_block bb, FILE *file); extern void df_print_bb_index (basic_block bb, FILE *file);
extern struct dataflow *df_ru_add_problem (struct df *); extern struct dataflow *df_ru_add_problem (struct df *, int);
extern struct df_ru_bb_info *df_ru_get_bb_info (struct dataflow *, unsigned int); extern struct df_ru_bb_info *df_ru_get_bb_info (struct dataflow *, unsigned int);
extern struct dataflow *df_rd_add_problem (struct df *); extern struct dataflow *df_rd_add_problem (struct df *, int);
extern struct df_rd_bb_info *df_rd_get_bb_info (struct dataflow *, unsigned int); extern struct df_rd_bb_info *df_rd_get_bb_info (struct dataflow *, unsigned int);
extern struct dataflow *df_lr_add_problem (struct df *); extern struct dataflow *df_lr_add_problem (struct df *, int);
extern struct df_lr_bb_info *df_lr_get_bb_info (struct dataflow *, unsigned int); extern struct df_lr_bb_info *df_lr_get_bb_info (struct dataflow *, unsigned int);
extern struct dataflow *df_ur_add_problem (struct df *); extern struct dataflow *df_ur_add_problem (struct df *, int);
extern struct df_ur_bb_info *df_ur_get_bb_info (struct dataflow *, unsigned int); extern struct df_ur_bb_info *df_ur_get_bb_info (struct dataflow *, unsigned int);
extern struct dataflow *df_urec_add_problem (struct df *); extern struct dataflow *df_urec_add_problem (struct df *, int);
extern struct df_urec_bb_info *df_urec_get_bb_info (struct dataflow *, unsigned int); extern struct df_urec_bb_info *df_urec_get_bb_info (struct dataflow *, unsigned int);
extern struct dataflow *df_chain_add_problem (struct df *, int flags); extern struct dataflow *df_chain_add_problem (struct df *, int);
extern struct dataflow *df_ri_add_problem (struct df *); extern struct dataflow *df_ri_add_problem (struct df *, int);
extern int df_reg_lifetime (struct df *, rtx reg);
/* Functions defined in df-scan.c. */ /* Functions defined in df-scan.c. */
extern struct df_scan_bb_info *df_scan_get_bb_info (struct dataflow *, unsigned int); extern struct df_scan_bb_info *df_scan_get_bb_info (struct dataflow *, unsigned int);
extern struct dataflow *df_scan_add_problem (struct df *); extern struct dataflow *df_scan_add_problem (struct df *, int);
extern void df_rescan_blocks (struct df *, bitmap); extern void df_rescan_blocks (struct df *, bitmap);
extern struct df_ref *df_ref_create (struct df *, rtx, rtx *, rtx,basic_block,enum df_ref_type, enum df_ref_flags); extern struct df_ref *df_ref_create (struct df *, rtx, rtx *, rtx,basic_block,enum df_ref_type, enum df_ref_flags);
extern struct df_ref *df_get_artificial_defs (struct df *, unsigned int); extern struct df_ref *df_get_artificial_defs (struct df *, unsigned int);
...@@ -588,7 +624,6 @@ extern void df_insn_refs_delete (struct dataflow *, rtx); ...@@ -588,7 +624,6 @@ extern void df_insn_refs_delete (struct dataflow *, rtx);
extern void df_bb_refs_delete (struct dataflow *, int); extern void df_bb_refs_delete (struct dataflow *, int);
extern void df_refs_delete (struct dataflow *, bitmap); extern void df_refs_delete (struct dataflow *, bitmap);
extern void df_reorganize_refs (struct df_ref_info *); extern void df_reorganize_refs (struct df_ref_info *);
extern void df_set_state (int);
extern void df_hard_reg_init (void); extern void df_hard_reg_init (void);
extern bool df_read_modify_subreg_p (rtx); extern bool df_read_modify_subreg_p (rtx);
......
...@@ -4026,6 +4026,9 @@ rest_of_clean_state (void) ...@@ -4026,6 +4026,9 @@ rest_of_clean_state (void)
epilogue_completed = 0; epilogue_completed = 0;
flow2_completed = 0; flow2_completed = 0;
no_new_pseudos = 0; no_new_pseudos = 0;
#ifdef STACK_REGS
regstack_completed = 0;
#endif
/* Clear out the insn_length contents now that they are no /* Clear out the insn_length contents now that they are no
longer valid. */ longer valid. */
......
...@@ -934,9 +934,9 @@ sms_schedule (void) ...@@ -934,9 +934,9 @@ sms_schedule (void)
sched_init (); sched_init ();
/* Init Data Flow analysis, to be used in interloop dep calculation. */ /* Init Data Flow analysis, to be used in interloop dep calculation. */
df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS); df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
df_rd_add_problem (df); df_rd_add_problem (df, 0);
df_ru_add_problem (df); df_ru_add_problem (df, 0);
df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN); df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
df_analyze (df); df_analyze (df);
......
...@@ -187,6 +187,8 @@ static VEC(char,heap) *stack_regs_mentioned_data; ...@@ -187,6 +187,8 @@ static VEC(char,heap) *stack_regs_mentioned_data;
#define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1) #define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1)
int regstack_completed = 0;
/* This is the basic stack record. TOP is an index into REG[] such /* This is the basic stack record. TOP is an index into REG[] such
that REG[TOP] is the top of stack. If TOP is -1 the stack is empty. that REG[TOP] is the top of stack. If TOP is -1 the stack is empty.
...@@ -3151,6 +3153,7 @@ rest_of_handle_stack_regs (void) ...@@ -3151,6 +3153,7 @@ rest_of_handle_stack_regs (void)
#ifdef STACK_REGS #ifdef STACK_REGS
if (reg_to_stack () && optimize) if (reg_to_stack () && optimize)
{ {
regstack_completed = 1;
if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
| (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)) | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0))
&& (flag_reorder_blocks || flag_reorder_blocks_and_partition)) && (flag_reorder_blocks || flag_reorder_blocks_and_partition))
...@@ -3159,6 +3162,8 @@ rest_of_handle_stack_regs (void) ...@@ -3159,6 +3162,8 @@ rest_of_handle_stack_regs (void)
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK); cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
} }
} }
else
regstack_completed = 1;
#endif #endif
return 0; return 0;
} }
......
...@@ -1978,6 +1978,12 @@ extern int epilogue_completed; ...@@ -1978,6 +1978,12 @@ extern int epilogue_completed;
extern int reload_in_progress; extern int reload_in_progress;
#ifdef STACK_REGS
/* Nonzero after end of regstack pass.
Set to 1 or 0 by reg-stack.c. */
extern int regstack_completed;
#endif
/* If this is nonzero, we do not bother generating VOLATILE /* If this is nonzero, we do not bother generating VOLATILE
around volatile memory references, and we are willing to around volatile memory references, and we are willing to
output indirect addresses. If cse is to follow, we reject output indirect addresses. If cse is to follow, we reject
......
...@@ -1323,9 +1323,8 @@ static void ...@@ -1323,9 +1323,8 @@ static void
see_initialize_data_structures (void) see_initialize_data_structures (void)
{ {
/* Build the df object. */ /* Build the df object. */
df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS); df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
df_rd_add_problem (df); df_rd_add_problem (df, 0);
/* df_ru_add_problem (df); */
df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN); df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
df_analyze (df); df_analyze (df);
......
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