summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-06-22 16:02:34 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-06-22 16:02:34 +0000
commit21256416bbcefcd911055bb0bc1c7119eec77403 (patch)
tree84b9b4144b79810bb743e2fb9bb71b47ba26829c /gcc
parente6c997e5d2734a24bf4d6e5e4e9022173a2347f5 (diff)
downloadgcc-21256416bbcefcd911055bb0bc1c7119eec77403.tar.gz
Fix version of patch from previous commit ;(
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161199 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/df-core.c76
-rw-r--r--gcc/df-problems.c12
-rw-r--r--gcc/df.h6
3 files changed, 60 insertions, 34 deletions
diff --git a/gcc/df-core.c b/gcc/df-core.c
index 814eaf41ccf..75f7bfe49ae 100644
--- a/gcc/df-core.c
+++ b/gcc/df-core.c
@@ -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.
+
+ 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).
-/* This will free "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)
diff --git a/gcc/df-problems.c b/gcc/df-problems.c
index 431027a41e0..1196e81e729 100644
--- a/gcc/df-problems.c
+++ b/gcc/df-problems.c
@@ -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);
}
diff --git a/gcc/df.h b/gcc/df.h
index b778c0f060c..fc3bb088ee5 100644
--- a/gcc/df.h
+++ b/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. */