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
This commit is contained in:
parent
d593cb3da7
commit
23249ac43c
166
gcc/df-core.c
166
gcc/df-core.c
@ -45,7 +45,7 @@ Here is an example of using the dataflow routines.
|
||||
|
||||
df = df_init (init_flags);
|
||||
|
||||
df_add_problem (df, problem);
|
||||
df_add_problem (df, problem, flags);
|
||||
|
||||
df_set_blocks (df, blocks);
|
||||
|
||||
@ -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
|
||||
and frees up any allocated memory.
|
||||
|
||||
There are two flags that can be passed to df_init:
|
||||
|
||||
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.
|
||||
There are three flags that can be passed to df_init, each of these
|
||||
flags controls the scanning of the rtl:
|
||||
|
||||
DF_HARD_REGS means that the scanning is to build information about
|
||||
both pseudo registers and hardware registers. Without this
|
||||
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_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
|
||||
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
|
||||
convenience functions named DF_*_ADD_PROBLEM.
|
||||
@ -297,7 +296,7 @@ are write-only operations.
|
||||
static struct df *ddf = 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 *);
|
||||
/*----------------------------------------------------------------------------
|
||||
Functions to create, destroy and manipulate an instance of df.
|
||||
@ -311,14 +310,13 @@ struct df *
|
||||
df_init (int flags)
|
||||
{
|
||||
struct df *df = XCNEW (struct df);
|
||||
df->flags = flags;
|
||||
|
||||
/* This is executed once per compilation to initialize platform
|
||||
specific data structures. */
|
||||
df_hard_reg_init ();
|
||||
|
||||
/* All df instance must define the scanning problem. */
|
||||
df_scan_add_problem (df);
|
||||
df_scan_add_problem (df, flags);
|
||||
ddf = df;
|
||||
return df;
|
||||
}
|
||||
@ -326,13 +324,13 @@ df_init (int flags)
|
||||
/* Add PROBLEM to the DF instance. */
|
||||
|
||||
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;
|
||||
|
||||
/* First try to add the dependent problem. */
|
||||
if (problem->dependent_problem)
|
||||
df_add_problem (df, problem->dependent_problem);
|
||||
if (problem->dependent_problem_fun)
|
||||
(problem->dependent_problem_fun) (df, 0);
|
||||
|
||||
/* 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
|
||||
@ -343,6 +341,7 @@ df_add_problem (struct df *df, struct df_problem *problem)
|
||||
|
||||
/* Make a new one and add it to the end. */
|
||||
dflow = XCNEW (struct dataflow);
|
||||
dflow->flags = flags;
|
||||
dflow->df = df;
|
||||
dflow->problem = problem;
|
||||
df->problems_in_order[df->num_problems_defined++] = dflow;
|
||||
@ -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
|
||||
not called or is called with null, the entire function in
|
||||
analyzed. */
|
||||
@ -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
|
||||
called from the df_finish macro which also NULLs the parm. */
|
||||
|
||||
@ -594,6 +643,8 @@ df_iterative_dataflow (struct dataflow *dataflow,
|
||||
sbitmap_zero (pending);
|
||||
sbitmap_zero (considered);
|
||||
|
||||
gcc_assert (dataflow->problem->dir);
|
||||
|
||||
EXECUTE_IF_SET_IN_BITMAP (blocks_to_consider, 0, idx, bi)
|
||||
{
|
||||
SET_BIT (considered, idx);
|
||||
@ -696,7 +747,7 @@ df_prune_to_subcfg (int list[], unsigned len, bitmap blocks)
|
||||
small fixup fringe sub sub
|
||||
*/
|
||||
|
||||
static void
|
||||
void
|
||||
df_analyze_problem (struct dataflow *dflow,
|
||||
bitmap blocks_to_consider,
|
||||
bitmap blocks_to_init,
|
||||
@ -705,7 +756,7 @@ df_analyze_problem (struct dataflow *dflow,
|
||||
{
|
||||
/* (Re)Allocate the datastructures necessary to solve the problem. */
|
||||
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
|
||||
function is passed both the blocks_to_consider and the
|
||||
@ -1066,7 +1117,7 @@ df_dump (struct df *df, FILE *file)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (! df || ! file)
|
||||
if (!df || !file)
|
||||
return;
|
||||
|
||||
fprintf (file, "\n\n%s\n", current_function_name ());
|
||||
@ -1082,8 +1133,7 @@ df_dump (struct df *df, FILE *file)
|
||||
|
||||
|
||||
void
|
||||
df_refs_chain_dump (struct df *df, struct df_ref *ref,
|
||||
bool follow_chain, FILE *file)
|
||||
df_refs_chain_dump (struct df_ref *ref, bool follow_chain, FILE *file)
|
||||
{
|
||||
fprintf (file, "{ ");
|
||||
while (ref)
|
||||
@ -1093,7 +1143,7 @@ df_refs_chain_dump (struct df *df, struct df_ref *ref,
|
||||
DF_REF_ID (ref),
|
||||
DF_REF_REGNO (ref));
|
||||
if (follow_chain)
|
||||
df_chain_dump (df, DF_REF_CHAIN (ref), file);
|
||||
df_chain_dump (DF_REF_CHAIN (ref), file);
|
||||
ref = ref->next_ref;
|
||||
}
|
||||
fprintf (file, "}");
|
||||
@ -1118,13 +1168,32 @@ df_regs_chain_dump (struct df *df ATTRIBUTE_UNUSED, struct df_ref *ref, FILE *f
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
df_insn_debug (struct df *df, rtx insn, bool follow_chain, FILE *file)
|
||||
static void
|
||||
df_mws_dump (struct df_mw_hardreg *mws, FILE *file)
|
||||
{
|
||||
unsigned int uid;
|
||||
int bbi;
|
||||
while (mws)
|
||||
{
|
||||
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))
|
||||
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)
|
||||
else
|
||||
bbi = -1;
|
||||
|
||||
fprintf (file, "insn %d bb %d luid %d defs ",
|
||||
uid, bbi, DF_INSN_LUID (df, insn));
|
||||
fprintf (file, "insn %d bb %d luid %d",
|
||||
uid, bbi, DF_INSN_UID_LUID (df, uid));
|
||||
|
||||
df_refs_chain_dump (df, DF_INSN_UID_DEFS (df, uid), follow_chain, file);
|
||||
fprintf (file, " defs ");
|
||||
df_refs_chain_dump (df, DF_INSN_UID_USES (df, uid), follow_chain, file);
|
||||
if (DF_INSN_UID_DEFS (df, uid))
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
|
||||
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 ",
|
||||
DF_REF_REG_DEF_P (ref) ? 'd' : 'u',
|
||||
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_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_chain_dump (df, DF_REF_CHAIN (ref), file);
|
||||
DF_REF_INSN (ref) ? INSN_UID (DF_REF_INSN (ref)) : -1,
|
||||
DF_REF_FLAGS (ref));
|
||||
df_chain_dump (DF_REF_CHAIN (ref), file);
|
||||
fprintf (file, "\n");
|
||||
}
|
||||
|
||||
@ -1218,27 +1308,27 @@ debug_df_regno (unsigned int regno)
|
||||
void
|
||||
debug_df_ref (struct df_ref *ref)
|
||||
{
|
||||
df_ref_debug (ddf, ref, stderr);
|
||||
df_ref_debug (ref, stderr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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
|
||||
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
|
||||
debug_df_chain (struct df_link *link)
|
||||
{
|
||||
df_chain_dump (ddf, link, stderr);
|
||||
df_chain_dump (link, stderr);
|
||||
fputc ('\n', stderr);
|
||||
}
|
||||
|
1004
gcc/df-problems.c
1004
gcc/df-problems.c
File diff suppressed because it is too large
Load Diff
421
gcc/df-scan.c
421
gcc/df-scan.c
@ -65,9 +65,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#define EPILOGUE_USES(REGNO) 0
|
||||
#endif
|
||||
|
||||
/* Indicates where we are in the compilation. */
|
||||
int df_state;
|
||||
|
||||
/* The bitmap_obstack is used to hold some static variables that
|
||||
should not be reset after each function is compiled. */
|
||||
|
||||
@ -122,6 +119,8 @@ struct df_scan_problem_data
|
||||
alloc_pool ref_pool;
|
||||
alloc_pool insn_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;
|
||||
@ -130,8 +129,8 @@ static void
|
||||
df_scan_free_internal (struct dataflow *dflow)
|
||||
{
|
||||
struct df *df = dflow->df;
|
||||
struct df_scan_problem_data *problem_data =
|
||||
(struct df_scan_problem_data *) dflow->problem_data;
|
||||
struct df_scan_problem_data *problem_data
|
||||
= (struct df_scan_problem_data *) dflow->problem_data;
|
||||
|
||||
free (df->def_info.regs);
|
||||
free (df->def_info.refs);
|
||||
@ -157,6 +156,8 @@ df_scan_free_internal (struct dataflow *dflow)
|
||||
free_alloc_pool (problem_data->ref_pool);
|
||||
free_alloc_pool (problem_data->insn_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)
|
||||
be rescanned. */
|
||||
|
||||
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_scan_problem_data *problem_data;
|
||||
@ -231,6 +233,12 @@ df_scan_alloc (struct dataflow *dflow, bitmap blocks_to_rescan)
|
||||
problem_data->reg_pool
|
||||
= create_alloc_pool ("df_scan_reg pool",
|
||||
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;
|
||||
df_grow_reg_info (dflow, &df->def_info);
|
||||
@ -319,7 +327,8 @@ static struct df_problem problem_SCAN =
|
||||
NULL, /* Finalize function. */
|
||||
df_scan_free, /* Free all of the problem information. */
|
||||
df_scan_dump, /* Debugging. */
|
||||
NULL /* Dependent problem. */
|
||||
NULL, /* Dependent problem. */
|
||||
0 /* Changeable flags. */
|
||||
};
|
||||
|
||||
|
||||
@ -328,9 +337,9 @@ static struct df_problem problem_SCAN =
|
||||
solution. */
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned int max_reg = max_reg_num ();
|
||||
unsigned int new_size = max_reg;
|
||||
struct df_scan_problem_data *problem_data =
|
||||
(struct df_scan_problem_data *) dflow->problem_data;
|
||||
struct df_scan_problem_data *problem_data
|
||||
= (struct df_scan_problem_data *) dflow->problem_data;
|
||||
unsigned int i;
|
||||
|
||||
if (ref_info->regs_size < new_size)
|
||||
@ -432,6 +441,9 @@ df_rescan_blocks (struct df *df, bitmap blocks)
|
||||
if (blocks)
|
||||
{
|
||||
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. */
|
||||
unsigned int insn_num = get_max_uid () + 1;
|
||||
@ -447,6 +459,20 @@ df_rescan_blocks (struct df *df, bitmap blocks)
|
||||
df_grow_bb_info (dflow);
|
||||
|
||||
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->use_info.add_refs_inline = true;
|
||||
|
||||
@ -490,7 +516,7 @@ df_rescan_blocks (struct df *df, bitmap blocks)
|
||||
{
|
||||
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->use_info.add_refs_inline = false;
|
||||
@ -508,6 +534,7 @@ df_rescan_blocks (struct df *df, bitmap blocks)
|
||||
BITMAP_FREE (local_blocks_to_scan);
|
||||
}
|
||||
|
||||
|
||||
/* Create a new ref of type DF_REF_TYPE for register REG at address
|
||||
LOC within INSN of BB. */
|
||||
|
||||
@ -634,8 +661,8 @@ df_reg_chain_unlink (struct dataflow *dflow, struct df_ref *ref)
|
||||
struct df *df = dflow->df;
|
||||
struct df_ref *next = DF_REF_NEXT_REG (ref);
|
||||
struct df_ref *prev = DF_REF_PREV_REG (ref);
|
||||
struct df_scan_problem_data *problem_data =
|
||||
(struct df_scan_problem_data *) dflow->problem_data;
|
||||
struct df_scan_problem_data *problem_data
|
||||
= (struct df_scan_problem_data *) dflow->problem_data;
|
||||
struct df_reg_info *reg_info;
|
||||
struct df_ref *next_ref = ref->next_ref;
|
||||
unsigned int id = DF_REF_ID (ref);
|
||||
@ -697,8 +724,8 @@ df_ref_remove (struct df *df, struct df_ref *ref)
|
||||
= df_ref_unlink (bb_info->artificial_defs, ref);
|
||||
}
|
||||
else
|
||||
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_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref))
|
||||
= df_ref_unlink (DF_INSN_UID_DEFS (df, DF_REF_INSN_UID (ref)), ref);
|
||||
|
||||
if (df->def_info.add_refs_inline)
|
||||
DF_DEFS_SET (df, DF_REF_ID (ref), NULL);
|
||||
@ -713,8 +740,8 @@ df_ref_remove (struct df *df, struct df_ref *ref)
|
||||
= df_ref_unlink (bb_info->artificial_uses, ref);
|
||||
}
|
||||
else
|
||||
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_INSN_UID_USES (df, DF_REF_INSN_UID (ref))
|
||||
= df_ref_unlink (DF_INSN_UID_USES (df, DF_REF_INSN_UID (ref)), ref);
|
||||
|
||||
if (df->use_info.add_refs_inline)
|
||||
DF_USES_SET (df, DF_REF_ID (ref), NULL);
|
||||
@ -730,8 +757,8 @@ static struct df_insn_info *
|
||||
df_insn_create_insn_record (struct dataflow *dflow, rtx insn)
|
||||
{
|
||||
struct df *df = dflow->df;
|
||||
struct df_scan_problem_data *problem_data =
|
||||
(struct df_scan_problem_data *) dflow->problem_data;
|
||||
struct df_scan_problem_data *problem_data
|
||||
= (struct df_scan_problem_data *) dflow->problem_data;
|
||||
|
||||
struct df_insn_info *insn_rec = DF_INSN_GET (df, insn);
|
||||
if (!insn_rec)
|
||||
@ -754,14 +781,31 @@ df_insn_refs_delete (struct dataflow *dflow, rtx insn)
|
||||
unsigned int uid = INSN_UID (insn);
|
||||
struct df_insn_info *insn_info = NULL;
|
||||
struct df_ref *ref;
|
||||
struct df_scan_problem_data *problem_data =
|
||||
(struct df_scan_problem_data *) dflow->problem_data;
|
||||
struct df_scan_problem_data *problem_data
|
||||
= (struct df_scan_problem_data *) dflow->problem_data;
|
||||
|
||||
if (uid < df->insns_size)
|
||||
insn_info = DF_INSN_UID_GET (df, uid);
|
||||
|
||||
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;
|
||||
while (ref)
|
||||
ref = df_reg_chain_unlink (dflow, ref);
|
||||
@ -875,20 +919,6 @@ df_reorganize_refs (struct df_ref_info *ref_info)
|
||||
ref_info->add_refs_inline = true;
|
||||
}
|
||||
|
||||
|
||||
/* 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,
|
||||
@ -906,8 +936,8 @@ df_ref_create_structure (struct dataflow *dflow, rtx reg, rtx *loc,
|
||||
struct df_ref *this_ref;
|
||||
struct df *df = dflow->df;
|
||||
int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
|
||||
struct df_scan_problem_data *problem_data =
|
||||
(struct df_scan_problem_data *) dflow->problem_data;
|
||||
struct df_scan_problem_data *problem_data
|
||||
= (struct df_scan_problem_data *) dflow->problem_data;
|
||||
|
||||
this_ref = pool_alloc (problem_data->ref_pool);
|
||||
DF_REF_REG (this_ref) = reg;
|
||||
@ -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
|
||||
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);
|
||||
reg_info->n_refs++;
|
||||
case DF_REF_REG_DEF:
|
||||
{
|
||||
struct df_reg_info *reg_info = DF_REG_DEF_GET (df, regno);
|
||||
reg_info->n_refs++;
|
||||
|
||||
/* Add the ref to the reg_def chain. */
|
||||
df_reg_chain_create (reg_info, this_ref);
|
||||
DF_REF_ID (this_ref) = df->def_info.bitmap_size;
|
||||
if (df->def_info.add_refs_inline)
|
||||
{
|
||||
if (DF_DEFS_SIZE (df) >= df->def_info.refs_size)
|
||||
{
|
||||
int new_size = df->def_info.bitmap_size
|
||||
+ df->def_info.bitmap_size / 4;
|
||||
df_grow_ref_info (&df->def_info, new_size);
|
||||
}
|
||||
/* 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++;
|
||||
|
||||
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;
|
||||
|
||||
/* Add the ref to the reg_def chain. */
|
||||
df_reg_chain_create (reg_info, this_ref);
|
||||
DF_REF_ID (this_ref) = df->def_info.bitmap_size;
|
||||
if (df->def_info.add_refs_inline)
|
||||
{
|
||||
if (DF_DEFS_SIZE (df) >= df->def_info.refs_size)
|
||||
{
|
||||
int new_size = df->def_info.bitmap_size
|
||||
+ df->def_info.bitmap_size / 4;
|
||||
df_grow_ref_info (&df->def_info, new_size);
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
case DF_REF_REG_MEM_LOAD:
|
||||
case DF_REF_REG_MEM_STORE:
|
||||
case DF_REF_REG_USE:
|
||||
{
|
||||
struct df_reg_info *reg_info = DF_REG_USE_GET (df, regno);
|
||||
reg_info->n_refs++;
|
||||
|
||||
/* Add the ref to the reg_use chain. */
|
||||
df_reg_chain_create (reg_info, this_ref);
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
df->def_info.bitmap_size++;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct df_reg_info *reg_info = DF_REG_USE_GET (df, regno);
|
||||
reg_info->n_refs++;
|
||||
|
||||
/* Add the ref to the reg_use chain. */
|
||||
df_reg_chain_create (reg_info, this_ref);
|
||||
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;
|
||||
}
|
||||
@ -1007,8 +1049,9 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
|
||||
enum df_ref_flags ref_flags,
|
||||
bool record_live)
|
||||
{
|
||||
unsigned int regno;
|
||||
struct df *df = dflow->df;
|
||||
rtx oldreg = reg;
|
||||
unsigned int regno;
|
||||
|
||||
gcc_assert (REG_P (reg) || GET_CODE (reg) == SUBREG);
|
||||
|
||||
@ -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
|
||||
(subreg:SI (reg:M A) N), with size(SImode) > size(Mmode).
|
||||
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_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (word_mode)
|
||||
|| GET_MODE_SIZE (GET_MODE (reg))
|
||||
@ -1031,10 +1074,13 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
|
||||
regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
|
||||
if (regno < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
int i;
|
||||
int endregno;
|
||||
unsigned int i;
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
SUBREG_BYTE (reg), GET_MODE (reg));
|
||||
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++)
|
||||
{
|
||||
struct df_ref *ref;
|
||||
|
||||
/* Calls are handled at call site because regs_ever_live
|
||||
doesn't include clobbered regs, only used ones. */
|
||||
if (ref_type == DF_REF_REG_DEF && record_live)
|
||||
@ -1061,14 +1129,22 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
|
||||
{
|
||||
/* Set regs_ever_live on uses of non-eliminable frame
|
||||
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 == ARG_POINTER_REGNUM)))
|
||||
regs_ever_live[i] = 1;
|
||||
}
|
||||
|
||||
df_ref_create_structure (dflow, regno_reg_rtx[i], loc,
|
||||
bb, insn, ref_type, ref_flags);
|
||||
ref = df_ref_create_structure (dflow, regno_reg_rtx[i], loc,
|
||||
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
|
||||
@ -1107,6 +1183,7 @@ df_def_record_1 (struct dataflow *dflow, rtx x,
|
||||
{
|
||||
rtx *loc;
|
||||
rtx dst;
|
||||
bool dst_in_strict_lowpart = false;
|
||||
|
||||
/* We may recursively call ourselves on EXPR_LIST when dealing with PARALLEL
|
||||
construct. */
|
||||
@ -1127,7 +1204,8 @@ df_def_record_1 (struct dataflow *dflow, rtx x,
|
||||
if (GET_CODE (temp) == EXPR_LIST || GET_CODE (temp) == CLOBBER
|
||||
|| GET_CODE (temp) == SET)
|
||||
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);
|
||||
}
|
||||
return;
|
||||
@ -1149,10 +1227,20 @@ df_def_record_1 (struct dataflow *dflow, rtx x,
|
||||
}
|
||||
#endif
|
||||
loc = &XEXP (dst, 0);
|
||||
if (GET_CODE (dst) == STRICT_LOW_PART)
|
||||
dst_in_strict_lowpart = true;
|
||||
dst = *loc;
|
||||
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)
|
||||
|| (GET_CODE (dst) == SUBREG && REG_P (SUBREG_REG (dst))))
|
||||
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)
|
||||
{
|
||||
/* Mark the single def within the pattern. */
|
||||
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)
|
||||
{
|
||||
@ -1232,7 +1320,7 @@ df_uses_record (struct dataflow *dflow, rtx *loc, enum df_ref_type ref_type,
|
||||
|
||||
case SUBREG:
|
||||
/* While we're here, optimize this case. */
|
||||
|
||||
flags |= DF_REF_PARTIAL;
|
||||
/* In case the SUBREG is not of a REG, do not optimize. */
|
||||
if (!REG_P (SUBREG_REG (x)))
|
||||
{
|
||||
@ -1424,8 +1512,8 @@ df_insn_contains_asm (rtx insn)
|
||||
static void
|
||||
df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
|
||||
{
|
||||
int i;
|
||||
struct df *df = dflow->df;
|
||||
int i;
|
||||
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
@ -1437,7 +1525,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
|
||||
/* Record register defs. */
|
||||
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;
|
||||
note = XEXP (note, 1))
|
||||
{
|
||||
@ -1490,7 +1578,7 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
|
||||
DF_REF_REG_USE, bb, insn,
|
||||
0);
|
||||
|
||||
if (df->flags & DF_HARD_REGS)
|
||||
if (dflow->flags & DF_HARD_REGS)
|
||||
{
|
||||
bitmap_iterator bi;
|
||||
unsigned int ui;
|
||||
@ -1502,8 +1590,8 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
|
||||
DF_REF_REG_USE, bb, insn,
|
||||
0);
|
||||
EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi)
|
||||
df_ref_record (dflow, regno_reg_rtx[ui], ®no_reg_rtx[ui], bb, insn,
|
||||
DF_REF_REG_DEF, DF_REF_CLOBBER, false);
|
||||
df_ref_record (dflow, regno_reg_rtx[ui], ®no_reg_rtx[ui], bb,
|
||||
insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1537,6 +1625,10 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
|
||||
rtx insn;
|
||||
int luid = 0;
|
||||
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. */
|
||||
if (!bb_info)
|
||||
@ -1561,7 +1653,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
|
||||
}
|
||||
|
||||
#ifdef EH_RETURN_DATA_REGNO
|
||||
if ((df->flags & DF_HARD_REGS)
|
||||
if ((dflow->flags & DF_HARD_REGS)
|
||||
&& df_has_eh_preds (bb))
|
||||
{
|
||||
unsigned int i;
|
||||
@ -1580,7 +1672,7 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
|
||||
#endif
|
||||
|
||||
|
||||
if ((df->flags & DF_HARD_REGS)
|
||||
if ((dflow->flags & DF_HARD_REGS)
|
||||
&& df_has_eh_preds (bb))
|
||||
{
|
||||
#ifdef EH_USES
|
||||
@ -1611,56 +1703,60 @@ df_bb_refs_record (struct dataflow *dflow, basic_block bb)
|
||||
{
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
df_uses_record (dflow, ®no_reg_rtx[FRAME_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
|
||||
bitmap_set_bit (artificial_uses_at_bottom, FRAME_POINTER_REGNUM);
|
||||
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
|
||||
df_uses_record (dflow, ®no_reg_rtx[HARD_FRAME_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
|
||||
bitmap_set_bit (artificial_uses_at_bottom, HARD_FRAME_POINTER_REGNUM);
|
||||
#endif
|
||||
}
|
||||
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||
if (fixed_regs[ARG_POINTER_REGNUM])
|
||||
df_uses_record (dflow, ®no_reg_rtx[ARG_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL,
|
||||
DF_REF_ARTIFICIAL);
|
||||
bitmap_set_bit (artificial_uses_at_bottom, ARG_POINTER_REGNUM);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if ((df->flags & DF_HARD_REGS)
|
||||
if ((dflow->flags & DF_HARD_REGS)
|
||||
&& bb->index >= NUM_FIXED_BLOCKS)
|
||||
{
|
||||
/* Before reload, there are a few registers that must be forced
|
||||
live everywhere -- which might not already be the case for
|
||||
blocks within infinite loops. */
|
||||
if (! reload_completed)
|
||||
if (!reload_completed)
|
||||
{
|
||||
|
||||
/* Any reference to any pseudo before reload is a potential
|
||||
reference of the frame pointer. */
|
||||
df_uses_record (dflow, ®no_reg_rtx[FRAME_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
|
||||
bitmap_set_bit (artificial_uses_at_bottom, FRAME_POINTER_REGNUM);
|
||||
|
||||
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||
/* Pseudos with argument area equivalences may require
|
||||
reloading via the argument pointer. */
|
||||
if (fixed_regs[ARG_POINTER_REGNUM])
|
||||
df_uses_record (dflow, ®no_reg_rtx[ARG_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL,
|
||||
DF_REF_ARTIFICIAL);
|
||||
bitmap_set_bit (artificial_uses_at_bottom, ARG_POINTER_REGNUM);
|
||||
#endif
|
||||
|
||||
/* Any constant, or pseudo with constant equivalences, may
|
||||
require reloading from memory using the pic register. */
|
||||
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
|
||||
&& fixed_regs[PIC_OFFSET_TABLE_REGNUM])
|
||||
df_uses_record (dflow, ®no_reg_rtx[PIC_OFFSET_TABLE_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL,
|
||||
DF_REF_ARTIFICIAL);
|
||||
bitmap_set_bit (artificial_uses_at_bottom, PIC_OFFSET_TABLE_REGNUM);
|
||||
}
|
||||
/* The all-important stack pointer must always be live. */
|
||||
df_uses_record (dflow, ®no_reg_rtx[STACK_POINTER_REGNUM],
|
||||
DF_REF_REG_USE, bb, NULL, DF_REF_ARTIFICIAL);
|
||||
bitmap_set_bit (artificial_uses_at_bottom, STACK_POINTER_REGNUM);
|
||||
}
|
||||
|
||||
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, ®no_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)
|
||||
entry to the function. */
|
||||
|
||||
static void
|
||||
df_record_entry_block_defs (struct dataflow * dflow)
|
||||
df_record_entry_block_defs (struct dataflow *dflow)
|
||||
{
|
||||
unsigned int i;
|
||||
bitmap_iterator bi;
|
||||
rtx r;
|
||||
struct df * df = dflow->df;
|
||||
struct df *df = dflow->df;
|
||||
|
||||
bitmap_clear (df->entry_block_defs);
|
||||
|
||||
if (! (df->flags & DF_HARD_REGS))
|
||||
if (!(dflow->flags & DF_HARD_REGS))
|
||||
return;
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
@ -1750,6 +1846,9 @@ df_record_entry_block_defs (struct dataflow * dflow)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The always important stack pointer. */
|
||||
bitmap_set_bit (df->entry_block_defs, STACK_POINTER_REGNUM);
|
||||
|
||||
#ifdef INCOMING_RETURN_ADDR_RTX
|
||||
if (REG_P (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)
|
||||
bitmap_set_bit (df->entry_block_defs, REGNO (r));
|
||||
}
|
||||
|
||||
/* These registers are live everywhere. */
|
||||
if (!reload_completed)
|
||||
if ((!reload_completed) || frame_pointer_needed)
|
||||
{
|
||||
/* Any reference to any pseudo before reload is a potential
|
||||
reference of the frame pointer. */
|
||||
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
|
||||
/* The ia-64, the only machine that uses this, does not define these
|
||||
until after reload. */
|
||||
@ -1826,15 +1933,15 @@ df_record_exit_block_uses (struct dataflow *dflow)
|
||||
|
||||
bitmap_clear (df->exit_block_uses);
|
||||
|
||||
if (! (df->flags & DF_HARD_REGS))
|
||||
if (!(dflow->flags & DF_HARD_REGS))
|
||||
return;
|
||||
|
||||
/* If exiting needs the right stack value, consider the stack
|
||||
pointer live at the end of the function. */
|
||||
if ((HAVE_epilogue && epilogue_completed)
|
||||
|| ! EXIT_IGNORE_STACK
|
||||
|| (! FRAME_POINTER_REQUIRED
|
||||
&& ! current_function_calls_alloca
|
||||
|| !EXIT_IGNORE_STACK
|
||||
|| (!FRAME_POINTER_REQUIRED
|
||||
&& !current_function_calls_alloca
|
||||
&& flag_omit_frame_pointer)
|
||||
|| current_function_sp_is_unchanging)
|
||||
{
|
||||
@ -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
|
||||
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);
|
||||
#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))
|
||||
if (!LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
|
||||
bitmap_set_bit (df->exit_block_uses, HARD_FRAME_POINTER_REGNUM);
|
||||
#endif
|
||||
}
|
||||
@ -1875,8 +1982,8 @@ df_record_exit_block_uses (struct dataflow *dflow)
|
||||
{
|
||||
/* Mark all call-saved registers that we actually used. */
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (regs_ever_live[i] && ! LOCAL_REGNO (i)
|
||||
&& ! TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
|
||||
if (regs_ever_live[i] && !LOCAL_REGNO (i)
|
||||
&& !TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
|
||||
bitmap_set_bit (df->exit_block_uses, i);
|
||||
}
|
||||
|
||||
@ -1893,7 +2000,7 @@ df_record_exit_block_uses (struct dataflow *dflow)
|
||||
#endif
|
||||
|
||||
#ifdef EH_RETURN_STACKADJ_RTX
|
||||
if ((! HAVE_epilogue || ! epilogue_completed)
|
||||
if ((!HAVE_epilogue || ! epilogue_completed)
|
||||
&& current_function_calls_eh_return)
|
||||
{
|
||||
rtx tmp = EH_RETURN_STACKADJ_RTX;
|
||||
@ -1903,7 +2010,7 @@ df_record_exit_block_uses (struct dataflow *dflow)
|
||||
#endif
|
||||
|
||||
#ifdef EH_RETURN_HANDLER_RTX
|
||||
if ((! HAVE_epilogue || ! epilogue_completed)
|
||||
if ((!HAVE_epilogue || ! epilogue_completed)
|
||||
&& current_function_calls_eh_return)
|
||||
{
|
||||
rtx tmp = EH_RETURN_HANDLER_RTX;
|
||||
@ -1915,7 +2022,7 @@ df_record_exit_block_uses (struct dataflow *dflow)
|
||||
/* Mark function return value. */
|
||||
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)
|
||||
df_uses_record (dflow, ®no_reg_rtx[i],
|
||||
DF_REF_REG_USE, EXIT_BLOCK_PTR, NULL,
|
||||
|
217
gcc/df.h
217
gcc/df.h
@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
struct dataflow;
|
||||
struct df;
|
||||
struct df_problem;
|
||||
struct df_link;
|
||||
|
||||
/* Data flow problems. All problems must have a unique here. */
|
||||
/* Scanning is not really a dataflow problem, but it is useful to have
|
||||
@ -49,10 +50,6 @@ struct df_problem;
|
||||
#define DF_RI 7 /* Register Info. */
|
||||
#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. */
|
||||
enum df_flow_dir
|
||||
@ -62,10 +59,72 @@ enum df_flow_dir
|
||||
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. */
|
||||
|
||||
/* 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
|
||||
to be cleared when ever the set of blocks changes. The bitmap
|
||||
@ -107,6 +166,10 @@ typedef void (*df_free_function) (struct dataflow *);
|
||||
/* Function to dump results to 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
|
||||
typedefs for doc for the function fields. */
|
||||
|
||||
@ -127,10 +190,10 @@ struct df_problem {
|
||||
df_finalizer_function finalize_fun;
|
||||
df_free_function free_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
|
||||
solved. */
|
||||
struct df_problem *dependent_problem;
|
||||
/* Flags can be changed after analysis starts. */
|
||||
int changeable_flags;
|
||||
};
|
||||
|
||||
|
||||
@ -151,6 +214,20 @@ struct dataflow
|
||||
/* The pool to allocate the block_info from. */
|
||||
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
|
||||
basis. The structure is generally defined privately for the
|
||||
problem. The exception being the scanning problem where it is
|
||||
@ -158,17 +235,35 @@ struct dataflow
|
||||
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. */
|
||||
struct df_insn_info
|
||||
{
|
||||
struct df_ref *defs; /* Head of insn-def 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
|
||||
we can change it on the fly to accommodate new insns? */
|
||||
int luid; /* Logical UID. */
|
||||
bool contains_asm; /* Contains an asm instruction. */
|
||||
};
|
||||
|
||||
|
||||
/* Two of these structures are allocated for every pseudo reg, one for
|
||||
the uses and one for the defs. */
|
||||
struct df_reg_info
|
||||
@ -178,48 +273,6 @@ struct df_reg_info
|
||||
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
|
||||
for every register reference (use or def). Note some register
|
||||
references (e.g., post_inc, subreg) generate both a def and a use. */
|
||||
@ -250,9 +303,9 @@ struct df_ref
|
||||
void *data; /* The data assigned to it by user. */
|
||||
};
|
||||
|
||||
/* There are two kinds of links: */
|
||||
|
||||
/* This is used for def-use or use-def chains. */
|
||||
/* These links are used for two purposes:
|
||||
1) def-use or use-def chains.
|
||||
2) Multiword hard registers that underly a single hardware register. */
|
||||
struct df_link
|
||||
{
|
||||
struct df_ref *ref;
|
||||
@ -288,12 +341,6 @@ struct df_ref_info
|
||||
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
|
||||
PROBLEMS_IN_ORDER, the problems are stored in the order that they
|
||||
are solved. This is an internally dense array that may have
|
||||
@ -379,7 +426,7 @@ struct df
|
||||
/* 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_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_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) \
|
||||
@ -398,8 +445,10 @@ struct df
|
||||
#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_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_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. */
|
||||
|
||||
@ -422,27 +471,13 @@ struct df
|
||||
#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_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
|
||||
easily add it into bitmaps, etc. */
|
||||
|
||||
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. */
|
||||
struct df_scan_bb_info
|
||||
@ -513,9 +548,13 @@ struct df_urec_bb_info
|
||||
/* Functions defined in df-core.c. */
|
||||
|
||||
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_delete_basic_block (struct df *, int);
|
||||
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_compact_blocks (struct df *);
|
||||
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);
|
||||
extern bool df_reg_used (struct df *, rtx, rtx);
|
||||
extern void df_iterative_dataflow (struct dataflow *, bitmap, bitmap, int *, int, bool);
|
||||
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 *, struct df_ref *, bool, FILE *);
|
||||
extern void df_refs_chain_dump (struct df_ref *, bool, 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_regno (struct df *, rtx, 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_regno (unsigned int);
|
||||
extern void debug_df_reg (rtx);
|
||||
@ -549,34 +587,32 @@ extern struct df *shared_df;
|
||||
|
||||
/* 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 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 bitmap df_get_live_in (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_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 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 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 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 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 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 dataflow *df_chain_add_problem (struct df *, int flags);
|
||||
extern struct dataflow *df_ri_add_problem (struct df *);
|
||||
extern int df_reg_lifetime (struct df *, rtx reg);
|
||||
extern struct dataflow *df_chain_add_problem (struct df *, int);
|
||||
extern struct dataflow *df_ri_add_problem (struct df *, int);
|
||||
|
||||
|
||||
/* Functions defined in df-scan.c. */
|
||||
|
||||
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 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);
|
||||
@ -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_refs_delete (struct dataflow *, bitmap);
|
||||
extern void df_reorganize_refs (struct df_ref_info *);
|
||||
extern void df_set_state (int);
|
||||
extern void df_hard_reg_init (void);
|
||||
extern bool df_read_modify_subreg_p (rtx);
|
||||
|
||||
|
@ -4026,6 +4026,9 @@ rest_of_clean_state (void)
|
||||
epilogue_completed = 0;
|
||||
flow2_completed = 0;
|
||||
no_new_pseudos = 0;
|
||||
#ifdef STACK_REGS
|
||||
regstack_completed = 0;
|
||||
#endif
|
||||
|
||||
/* Clear out the insn_length contents now that they are no
|
||||
longer valid. */
|
||||
|
@ -934,9 +934,9 @@ sms_schedule (void)
|
||||
sched_init ();
|
||||
|
||||
/* Init Data Flow analysis, to be used in interloop dep calculation. */
|
||||
df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
|
||||
df_rd_add_problem (df);
|
||||
df_ru_add_problem (df);
|
||||
df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
|
||||
df_rd_add_problem (df, 0);
|
||||
df_ru_add_problem (df, 0);
|
||||
df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
|
||||
df_analyze (df);
|
||||
|
||||
|
@ -187,6 +187,8 @@ static VEC(char,heap) *stack_regs_mentioned_data;
|
||||
|
||||
#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
|
||||
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)
|
||||
#ifdef STACK_REGS
|
||||
if (reg_to_stack () && optimize)
|
||||
{
|
||||
regstack_completed = 1;
|
||||
if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
|
||||
| (flag_crossjumping ? CLEANUP_CROSSJUMP : 0))
|
||||
&& (flag_reorder_blocks || flag_reorder_blocks_and_partition))
|
||||
@ -3159,6 +3162,8 @@ rest_of_handle_stack_regs (void)
|
||||
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
|
||||
}
|
||||
}
|
||||
else
|
||||
regstack_completed = 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -1978,6 +1978,12 @@ extern int epilogue_completed;
|
||||
|
||||
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
|
||||
around volatile memory references, and we are willing to
|
||||
output indirect addresses. If cse is to follow, we reject
|
||||
|
@ -1323,9 +1323,8 @@ static void
|
||||
see_initialize_data_structures (void)
|
||||
{
|
||||
/* Build the df object. */
|
||||
df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
|
||||
df_rd_add_problem (df);
|
||||
/* df_ru_add_problem (df); */
|
||||
df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
|
||||
df_rd_add_problem (df, 0);
|
||||
df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
|
||||
df_analyze (df);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user