Fix version of patch from previous commit ;(
From-SVN: r161199
This commit is contained in:
parent
c42bfef297
commit
50b2e85996
@ -851,12 +851,25 @@ struct rtl_opt_pass pass_df_finish =
|
||||
The general data flow analysis engine.
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/* Return time BB when it was visited for last time. */
|
||||
#define BB_LAST_CHANGE_AGE(bb) ((ptrdiff_t)(bb)->aux)
|
||||
|
||||
/* Helper function for df_worklist_dataflow.
|
||||
Propagate the dataflow forward.
|
||||
Given a BB_INDEX, do the dataflow propagation
|
||||
and set bits on for successors in PENDING
|
||||
if the out set of the dataflow has changed. */
|
||||
if the out set of the dataflow has changed.
|
||||
|
||||
AGE specify time when BB was visited last time.
|
||||
AGE of 0 means we are visiting for first time and need to
|
||||
compute transfer function to initialize datastructures.
|
||||
Otherwise we re-do transfer function only if something change
|
||||
while computing confluence functions.
|
||||
We need to compute confluence only of basic block that are younger
|
||||
then last visit of the BB.
|
||||
|
||||
Return true if BB info has changed. This is always the case
|
||||
in the first visit. */
|
||||
|
||||
static bool
|
||||
df_worklist_propagate_forward (struct dataflow *dataflow,
|
||||
@ -864,7 +877,7 @@ df_worklist_propagate_forward (struct dataflow *dataflow,
|
||||
unsigned *bbindex_to_postorder,
|
||||
bitmap pending,
|
||||
sbitmap considered,
|
||||
size_t age)
|
||||
ptrdiff_t age)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
@ -875,15 +888,12 @@ df_worklist_propagate_forward (struct dataflow *dataflow,
|
||||
if (EDGE_COUNT (bb->preds) > 0)
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
{
|
||||
if ((age <= (size_t)e->src->aux)
|
||||
&& TEST_BIT (considered, e->src->index))
|
||||
if (age <= BB_LAST_CHANGE_AGE (e->src)
|
||||
&& TEST_BIT (considered, e->src->index))
|
||||
changed |= dataflow->problem->con_fun_n (e);
|
||||
}
|
||||
else if (dataflow->problem->con_fun_0)
|
||||
{
|
||||
dataflow->problem->con_fun_0 (bb);
|
||||
changed = true;
|
||||
}
|
||||
dataflow->problem->con_fun_0 (bb);
|
||||
|
||||
if (changed
|
||||
&& dataflow->problem->trans_fun (bb_index))
|
||||
@ -912,7 +922,7 @@ df_worklist_propagate_backward (struct dataflow *dataflow,
|
||||
unsigned *bbindex_to_postorder,
|
||||
bitmap pending,
|
||||
sbitmap considered,
|
||||
size_t age)
|
||||
ptrdiff_t age)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
@ -923,15 +933,12 @@ df_worklist_propagate_backward (struct dataflow *dataflow,
|
||||
if (EDGE_COUNT (bb->succs) > 0)
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
{
|
||||
if ((age <= (size_t)e->dest->aux)
|
||||
&& TEST_BIT (considered, e->dest->index))
|
||||
if (age <= BB_LAST_CHANGE_AGE (e->dest)
|
||||
&& TEST_BIT (considered, e->dest->index))
|
||||
changed |= dataflow->problem->con_fun_n (e);
|
||||
}
|
||||
else if (dataflow->problem->con_fun_0)
|
||||
{
|
||||
dataflow->problem->con_fun_0 (bb);
|
||||
changed = true;
|
||||
}
|
||||
dataflow->problem->con_fun_0 (bb);
|
||||
|
||||
if (changed
|
||||
&& dataflow->problem->trans_fun (bb_index))
|
||||
@ -950,10 +957,24 @@ df_worklist_propagate_backward (struct dataflow *dataflow,
|
||||
return false;
|
||||
}
|
||||
|
||||
DEF_VEC_I(size_t);
|
||||
DEF_VEC_ALLOC_I(size_t,heap);
|
||||
/* Main dataflow solver loop.
|
||||
|
||||
/* This will free "pending". */
|
||||
DATAFLOW is problem we are solving, PENDING is worklist of basic blocks we
|
||||
need to visit.
|
||||
BLOCK_IN_POSTORDER is array of size N_BLOCKS specifying postorder in BBs and
|
||||
BBINDEX_TO_POSTORDER is array mapping back BB->index to postorder possition.
|
||||
PENDING will be freed.
|
||||
|
||||
The worklists are bitmaps indexed by postorder positions.
|
||||
|
||||
The function implements standard algorithm for dataflow solving with two
|
||||
worklists (we are processing WORKLIST and storing new BBs to visit in
|
||||
PENDING).
|
||||
|
||||
As an optimization we maintain ages when BB was changed (stored in bb->aux)
|
||||
and when it was last visited (stored in last_visit_age). This avoids need
|
||||
to re-do confluence function for edges to basic blocks whose source
|
||||
did not change since destination was visited last time. */
|
||||
|
||||
static void
|
||||
df_worklist_dataflow_doublequeue (struct dataflow *dataflow,
|
||||
@ -966,14 +987,14 @@ df_worklist_dataflow_doublequeue (struct dataflow *dataflow,
|
||||
enum df_flow_dir dir = dataflow->problem->dir;
|
||||
int dcount = 0;
|
||||
bitmap worklist = BITMAP_ALLOC (&df_bitmap_obstack);
|
||||
size_t age = 0;
|
||||
int age = 0;
|
||||
bool changed;
|
||||
VEC(size_t, heap) *last_age = NULL;
|
||||
size_t prev_age;
|
||||
VEC(int, heap) *last_visit_age = NULL;
|
||||
int prev_age;
|
||||
basic_block bb;
|
||||
int i;
|
||||
|
||||
VEC_safe_grow_cleared (size_t, heap, last_age, n_blocks);
|
||||
VEC_safe_grow_cleared (int, heap, last_visit_age, n_blocks);
|
||||
|
||||
/* Double-queueing. Worklist is for the current iteration,
|
||||
and pending is for the next. */
|
||||
@ -992,9 +1013,10 @@ df_worklist_dataflow_doublequeue (struct dataflow *dataflow,
|
||||
unsigned bb_index;
|
||||
dcount++;
|
||||
|
||||
bitmap_clear_bit (pending, index);
|
||||
bb_index = blocks_in_postorder[index];
|
||||
bb = BASIC_BLOCK (bb_index);
|
||||
prev_age = VEC_index (size_t, last_age, index);
|
||||
prev_age = VEC_index (int, last_visit_age, index);
|
||||
if (dir == DF_FORWARD)
|
||||
changed = df_worklist_propagate_forward (dataflow, bb_index,
|
||||
bbindex_to_postorder,
|
||||
@ -1005,11 +1027,9 @@ df_worklist_dataflow_doublequeue (struct dataflow *dataflow,
|
||||
bbindex_to_postorder,
|
||||
pending, considered,
|
||||
prev_age);
|
||||
age++;
|
||||
VEC_replace (int, last_visit_age, index, ++age);
|
||||
if (changed)
|
||||
bb->aux = (void *)age;
|
||||
VEC_replace (size_t, last_age, index, age);
|
||||
age++;
|
||||
bb->aux = (void *)(ptrdiff_t)age;
|
||||
}
|
||||
bitmap_clear (worklist);
|
||||
}
|
||||
@ -1018,7 +1038,7 @@ df_worklist_dataflow_doublequeue (struct dataflow *dataflow,
|
||||
|
||||
BITMAP_FREE (worklist);
|
||||
BITMAP_FREE (pending);
|
||||
VEC_free (size_t, heap, last_age);
|
||||
VEC_free (int, heap, last_visit_age);
|
||||
|
||||
/* Dump statistics. */
|
||||
if (dump_file)
|
||||
|
@ -983,7 +983,8 @@ df_lr_confluence_n (edge e)
|
||||
else
|
||||
changed = bitmap_ior_into (op1, op2);
|
||||
|
||||
return bitmap_ior_into (op1, &df->hardware_regs_used) || changed;
|
||||
changed |= bitmap_ior_into (op1, &df->hardware_regs_used);
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@ -2726,11 +2727,13 @@ df_byte_lr_confluence_n (edge e)
|
||||
/* ??? Abnormal call edges ignored for the moment, as this gets
|
||||
confused by sibling call edges, which crashes reg-stack. */
|
||||
if (e->flags & EDGE_EH)
|
||||
changed = bitmap_ior_and_compl_into (op1, op2, &problem_data->invalidated_by_call);
|
||||
changed = bitmap_ior_and_compl_into (op1, op2,
|
||||
&problem_data->invalidated_by_call);
|
||||
else
|
||||
changed = bitmap_ior_into (op1, op2);
|
||||
|
||||
return bitmap_ior_into (op1, &problem_data->hardware_regs_used) || changed;
|
||||
changed |= bitmap_ior_into (op1, &problem_data->hardware_regs_used);
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
@ -4440,7 +4443,8 @@ df_md_confluence_n (edge e)
|
||||
return false;
|
||||
|
||||
if (e->flags & EDGE_EH)
|
||||
return bitmap_ior_and_compl_into (op1, op2, regs_invalidated_by_call_regset);
|
||||
return bitmap_ior_and_compl_into (op1, op2,
|
||||
regs_invalidated_by_call_regset);
|
||||
else
|
||||
return bitmap_ior_into (op1, op2);
|
||||
}
|
||||
|
6
gcc/df.h
6
gcc/df.h
@ -222,10 +222,12 @@ typedef void (*df_dataflow_function) (struct dataflow *, bitmap, int *, int);
|
||||
/* Confluence operator for blocks with 0 out (or in) edges. */
|
||||
typedef void (*df_confluence_function_0) (basic_block);
|
||||
|
||||
/* Confluence operator for blocks with 1 or more out (or in) edges. */
|
||||
/* Confluence operator for blocks with 1 or more out (or in) edges.
|
||||
Return true if BB input data has changed. */
|
||||
typedef bool (*df_confluence_function_n) (edge);
|
||||
|
||||
/* Transfer function for blocks. */
|
||||
/* Transfer function for blocks.
|
||||
Return true if BB output data has changed. */
|
||||
typedef bool (*df_transfer_function) (int);
|
||||
|
||||
/* Function to massage the information after the problem solving. */
|
||||
|
Loading…
Reference in New Issue
Block a user