This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix the LOOP_BRANCH prediction


On Tue, Jul 31, 2012 at 12:20 PM, Dehao Chen <dehao@google.com> wrote:
> Are you suggesting a patch like this:
>
> Index: gcc/predict.c
> ===================================================================
> --- gcc/predict.c       (revision 189835)
> +++ gcc/predict.c       (working copy)
> @@ -1319,6 +1319,7 @@
>        tree loop_bound_var = NULL;
>        tree loop_iv_base = NULL;
>        gimple stmt = NULL;
> +      int header_found = 0;
>
>        exits = get_loop_exit_edges (loop);
>        n_exits = VEC_length (edge, exits);
> @@ -1387,9 +1388,20 @@
>
>        bbs = get_loop_body (loop);
>
> +      /* Loop branch heuristics - predict an edge back to a
> +        loop's head as taken.  */
> +      if (loop->latch && loop->latch->loop_father == loop)

Hmm, so the issue is that loop->latch does not belong to loop?  That looks
like a bogus loop structure.  Indeed we have the loop header of the inner
loop as latch of the outer loop.  It still looks ok to predict this as unlikely
as the edge is not only the latch edge of the outer loop but also an exit
of the inner loop.

Easier for profile would be to force canonicalization via

  loop_optimizer_init (LOOPS_NORMAL);

instead of

  loop_optimizer_init (0);
  if (dump_file && (dump_flags & TDF_DETAILS))
    flow_loops_dump (dump_file, NULL, 0);

  mark_irreducible_loops ();


> +       {
> +         edge e = find_edge (loop->latch, loop->header);
> +         if (e)
> +           {
> +             header_found = 1;
> +             predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
> +           }
> +       }
> +
>        for (j = 0; j < loop->num_nodes; j++)
>         {
> -         int header_found = 0;
>           edge e;
>           edge_iterator ei;
>
> @@ -1402,21 +1414,9 @@
>           if (predicted_by_p (bb, PRED_CONTINUE))
>             continue;
>
> -         /* Loop branch heuristics - predict an edge back to a
> -            loop's head as taken.  */
> -         if (bb == loop->latch)
> -           {
> -             e = find_edge (loop->latch, loop->header);
> -             if (e)
> -               {
> -                 header_found = 1;
> -                 predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
> -               }
> -           }
> -

Yes until here,

>           /* Loop exit heuristics - predict an edge exiting the loop if the
>              conditional has no loop header successors as not taken.  */
> -         if (!header_found
> +         if (!(header_found && bb == loop->latch)

here instead

                  !header_found
                  && bb->loop_father == loop

>               /* If we already used more reliable loop exit predictors, do not
>                  bother with PRED_LOOP_EXIT.  */
>               && !predicted_by_p (bb, PRED_LOOP_ITERATIONS_GUESSED)
>
> On Tue, Jul 31, 2012 at 5:18 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Tue, Jul 31, 2012 at 5:17 AM, Dehao Chen <dehao@google.com> wrote:
>>> Hi,
>>>
>>> This patch fixed the problem when a LOOP_EXIT edge for the inner loop
>>> happened to target at the LOOP_LATCH of the outer loop. As the outer
>>> loop is processed first, the LOOP_BRANCH heuristic is honored
>>> (first_match), thus the inner loop's trip count is 0. (The attached
>>> unittest demonstrates this).
>>>
>>> Bootstrapped and passed gcc regression test.
>>>
>>> Is it ok for trunk?
>>>
>>> Thanks,
>>> Dehao
>>>
>>> gcc/ChangeLog
>>>
>>> 2012-07-30  Dehao Chen  <dehao@google.com>
>>>
>>>         * predict.c (predict_loops): Fix the prediction of LOOP_BRANCH.
>>>
>>> gcc/testsuite/ChangeLog
>>>
>>> 2012-07-31  Dehao Chen  <dehao@google.com>
>>>
>>>         * gcc.dg/predict-7.c: New test.
>>>
>>> Index: gcc/testsuite/gcc.dg/predict-7.c
>>> ===================================================================
>>> --- gcc/testsuite/gcc.dg/predict-7.c    (revision 0)
>>> +++ gcc/testsuite/gcc.dg/predict-7.c    (revision 0)
>>> @@ -0,0 +1,17 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
>>> +
>>> +extern int global;
>>> +
>>> +int bar (int);
>>> +
>>> +void foo (int base)
>>> +{
>>> +  int i;
>>> +  while (global < 10)
>>> +    for (i = base; i < 10; i++)
>>> +      bar (i);
>>> +}
>>> +
>>> +/* { dg-final { scan-tree-dump-times "loop branch heuristics" 0
>>> "profile_estimate"} } */
>>> +/* { dg-final { cleanup-tree-dump "profile_estimate" } } */
>>> Index: gcc/predict.c
>>> ===================================================================
>>> --- gcc/predict.c       (revision 189835)
>>> +++ gcc/predict.c       (working copy)
>>> @@ -1404,7 +1404,7 @@
>>>
>>>           /* Loop branch heuristics - predict an edge back to a
>>>              loop's head as taken.  */
>>> -         if (bb == loop->latch)
>>> +         if (bb == loop->latch && bb->loop_father == loop)
>>>             {
>>>               e = find_edge (loop->latch, loop->header);
>>>               if (e)
>>
>> I think this heuristic should instead move out of the loop iterating over loop
>> nodes and be done before like
>>
>>   if (loop->latch)
>>     {
>>        e = find_edge (loop->latch, loop->header);
>>        ...
>>     }
>>
>> which also makes header_found initialized before we visit loop blocks.
>>
>> Instead the code
>>
>>           /* Loop exit heuristics - predict an edge exiting the loop if the
>>              conditional has no loop header successors as not taken.  */
>>           if (!header_found
>>               /* If we already used more reliable loop exit predictors, do not
>>                  bother with PRED_LOOP_EXIT.  */
>> ...
>>               FOR_EACH_EDGE (e, ei, bb->succs)
>>                 if (e->dest->index < NUM_FIXED_BLOCKS
>>                     || !flow_bb_inside_loop_p (loop, e->dest))
>>                   predict_edge (e, PRED_LOOP_EXIT, probability);
>>
>> looks wrong for bb's that are parts of an inner loop of loop - assuming we
>> only want to predicate exits from loop and not exits from an inner loop
>> that also happen to exit loop (we will do that when predicating the inner loop).
>
> You are right. And if we want to change this, we'd also need to modify
> get_loop_exit_edges to only count edges whose src is in the same loop
> level. However, this is relatively minor issue because it only
> predicts inaccurate bias ratio, while in the testcase I gave,
> LOOP_BRANCH is predicting in the wrong direction.
>
> Thanks,
> Dehao
>
>
>>
>> Is that what you experienced?
>>
>> Thanks,
>> Richard.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]