df = df_init (init_flags);
- df_add_problem (df, problem);
+ df_add_problem (df, problem, flags);
df_set_blocks (df, blocks);
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.
DF_ANALYZE causes all of the defined problems to be (re)solved. It
does not cause blocks to be (re)scanned at the rtl level unless no
-prior call is made to df_rescan_blocks.
+prior call is made to df_rescan_blocks. When DF_ANALYZE is completes,
+the IN and OUT sets for each basic block contain the computer
+information. The DF_*_BB_INFO macros can be used to access these
+bitvectors.
DF_DUMP can then be called to dump the information produce to some
As for the bit vector problems, there is no interface to give a set of
blocks over with to resolve the iteration. In general, restarting a
dataflow iteration is difficult and expensive. Again, the best way to
-keep the dataflow infomation up to data (if this is really what is
+keep the dataflow information up to data (if this is really what is
needed) it to formulate a problem specific solution.
There are fine grained calls for creating and deleting references from
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.
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;
}
/* 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
/* 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;
}
+/* 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. */
}
+/* 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. */
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);
small fixup fringe sub sub
*/
-static void
+void
df_analyze_problem (struct dataflow *dflow,
bitmap blocks_to_consider,
bitmap blocks_to_init,
{
/* (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
{
rtx insn;
struct df_ref *use;
+ unsigned int uid;
FOR_BB_INSNS_REVERSE (bb, insn)
{
- unsigned int uid = INSN_UID (insn);
+ if (!INSN_P (insn))
+ continue;
+
+ uid = INSN_UID (insn);
for (use = DF_INSN_UID_GET (df, uid)->uses; use; use = use->next_ref)
if (DF_REF_REGNO (use) == regno)
return use;
{
rtx insn;
struct df_ref *def;
+ unsigned int uid;
FOR_BB_INSNS (bb, insn)
{
- unsigned int uid = INSN_UID (insn);
+ if (!INSN_P (insn))
+ continue;
+
+ uid = INSN_UID (insn);
for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref)
if (DF_REF_REGNO (def) == regno)
return def;
{
rtx insn;
struct df_ref *def;
+ unsigned int uid;
FOR_BB_INSNS_REVERSE (bb, insn)
{
- unsigned int uid = INSN_UID (insn);
+ if (!INSN_P (insn))
+ continue;
+ uid = INSN_UID (insn);
for (def = DF_INSN_UID_GET (df, uid)->defs; def; def = def->next_ref)
if (DF_REF_REGNO (def) == regno)
return def;
{
int i;
- if (! df || ! file)
+ if (!df || !file)
return;
fprintf (file, "\n\n%s\n", current_function_name ());
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)
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, "}");
}
-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));
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));
+
+ 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);
+ }
- 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_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)
{
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");
}
\f
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);
}