On March 12, 2020 11:29:45 PM GMT+01:00, Segher Boessenkool
<[email protected]> wrote:
>The df dataflow solvers use the aux field in the basic_block struct,
>although that is reserved for any use by passes. And not only that,
>it is required that you set all such fields to NULL before calling
>the solvers, or you quietly get wrong results.
>
>This changes the solvers to use a local array for last_change_age
>instead, just like it already had a local array for last_visit_age.
>
>Tested on powerpc64-linux {-m32,-m64}. Also tested with the tests for
>PR94042, which it also solves (I need to confirm that still though,
>there are other testsuite problems interfering with my testing).
OK for trunk and affected branches (can you report back how old this issue is?)
Thanks,
Richard.
> PR rtl-optimization/94148
> PR rtl-optimization/94042
> * df-core.c (BB_LAST_CHANGE_AGE): Delete.
> (df_worklist_propagate_forward): New parameter last_change_age, use
> that instead of bb->aux.
> (df_worklist_propagate_backward): Ditto.
> (df_worklist_dataflow_doublequeue): Use a local array last_change_age.
>
>---
> gcc/df-core.c | 35 ++++++++++++++++++-----------------
> 1 file changed, 18 insertions(+), 17 deletions(-)
>
>diff --git a/gcc/df-core.c b/gcc/df-core.c
>index 346849e..9875a26 100644
>--- a/gcc/df-core.c
>+++ b/gcc/df-core.c
>@@ -871,9 +871,6 @@ make_pass_df_finish (gcc::context *ctxt)
> 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
>@@ -897,7 +894,8 @@ df_worklist_propagate_forward (struct dataflow
>*dataflow,
> unsigned *bbindex_to_postorder,
> bitmap pending,
> sbitmap considered,
>- ptrdiff_t age)
>+ vec<int> &last_change_age,
>+ int age)
> {
> edge e;
> edge_iterator ei;
>@@ -908,7 +906,8 @@ df_worklist_propagate_forward (struct dataflow
>*dataflow,
> if (EDGE_COUNT (bb->preds) > 0)
> FOR_EACH_EDGE (e, ei, bb->preds)
> {
>- if (age <= BB_LAST_CHANGE_AGE (e->src)
>+ if (bbindex_to_postorder[e->src->index] < last_change_age.length ()
>+ && age <= last_change_age[bbindex_to_postorder[e->src->index]]
> && bitmap_bit_p (considered, e->src->index))
> changed |= dataflow->problem->con_fun_n (e);
> }
>@@ -942,7 +941,8 @@ df_worklist_propagate_backward (struct dataflow
>*dataflow,
> unsigned *bbindex_to_postorder,
> bitmap pending,
> sbitmap considered,
>- ptrdiff_t age)
>+ vec<int> &last_change_age,
>+ int age)
> {
> edge e;
> edge_iterator ei;
>@@ -953,7 +953,8 @@ df_worklist_propagate_backward (struct dataflow
>*dataflow,
> if (EDGE_COUNT (bb->succs) > 0)
> FOR_EACH_EDGE (e, ei, bb->succs)
> {
>- if (age <= BB_LAST_CHANGE_AGE (e->dest)
>+ if (bbindex_to_postorder[e->dest->index] < last_change_age.length ()
>+ && age <= last_change_age[bbindex_to_postorder[e->dest->index]]
> && bitmap_bit_p (considered, e->dest->index))
> changed |= dataflow->problem->con_fun_n (e);
> }
>@@ -991,10 +992,10 @@ df_worklist_propagate_backward (struct dataflow
>*dataflow,
> 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. */
>+ As an optimization we maintain ages when BB was changed (stored in
>+ last_change_age) 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,
>@@ -1010,11 +1011,11 @@ df_worklist_dataflow_doublequeue (struct
>dataflow *dataflow,
> int age = 0;
> bool changed;
> vec<int> last_visit_age = vNULL;
>+ vec<int> last_change_age = vNULL;
> int prev_age;
>- basic_block bb;
>- int i;
>
> last_visit_age.safe_grow_cleared (n_blocks);
>+ last_change_age.safe_grow_cleared (n_blocks);
>
> /* Double-queueing. Worklist is for the current iteration,
> and pending is for the next. */
>@@ -1032,30 +1033,30 @@ df_worklist_dataflow_doublequeue (struct
>dataflow *dataflow,
>
> bitmap_clear_bit (pending, index);
> bb_index = blocks_in_postorder[index];
>- bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
> prev_age = last_visit_age[index];
> if (dir == DF_FORWARD)
> changed = df_worklist_propagate_forward (dataflow, bb_index,
> bbindex_to_postorder,
> pending, considered,
>+ last_change_age,
> prev_age);
> else
> changed = df_worklist_propagate_backward (dataflow, bb_index,
> bbindex_to_postorder,
> pending, considered,
>+ last_change_age,
> prev_age);
> last_visit_age[index] = ++age;
> if (changed)
>- bb->aux = (void *)(ptrdiff_t)age;
>+ last_change_age[index] = age;
> }
> bitmap_clear (worklist);
> }
>- for (i = 0; i < n_blocks; i++)
>- BASIC_BLOCK_FOR_FN (cfun, blocks_in_postorder[i])->aux = NULL;
>
> BITMAP_FREE (worklist);
> BITMAP_FREE (pending);
> last_visit_age.release ();
>+ last_change_age.release ();
>
> /* Dump statistics. */
> if (dump_file)