Hi,
> gcc/ChangeLog:
> 
>       PR tree-optimization/117790
>       * cfgloopmanip.cc (can_flow_scale_loop_freqs_p): New.
>       (flow_scale_loop_freqs): New.
>       (scale_loop_freqs_with_exit_counts): New.
>       (scale_loop_freqs_hold_exit_counts): New.
>       (scale_loop_profile): Refactor to use the newly-added
>       scale_loop_profile_1, and use scale_loop_freqs_hold_exit_counts to
>       correctly handle reducing the expected niters for loops with multiple
>       exits.
>       (scale_loop_freqs_with_new_exit_count): New.
>       (scale_loop_profile_1): New.
>       (scale_loop_profile_hold_exit_counts): New.
>       * cfgloopmanip.h (scale_loop_profile_hold_exit_counts): New.
>       (scale_loop_freqs_with_new_exit_count): New.
+template<typename ExitCountFn>
+static bool
+can_flow_scale_loop_freqs_p (class loop *loop,
+                            ExitCountFn get_exit_count)
+{
+  basic_block bb = loop->header;
+
+  const profile_count count_in = loop_count_in (loop);
+  profile_count exit_count = profile_count::zero ();
+
+  while (bb != loop->latch)
+    {
+      /* Punt if any of the BB counts are uninitialized.  */
+      if (!bb->count.initialized_p ())
+       return false;
+
+      bool found_exit = false;
+      edge internal_edge = nullptr;
+      for (auto e : bb->succs)
+       if (flow_bb_inside_loop_p (loop, e->dest))
+         {
+           if (internal_edge)
+             return false;
+           internal_edge = e;

This assumes that there are at most 2 edges out which is not always the
case (i.e. for EH and switch).  I suppose vectorizer never calls it
there but probably you want to test that there are precisely two edges
in can_flow_scale_loop_freqs and if not drop message to dump file, so in
case we encounter such loops we notice.

+         }
+       else
+         {
+           if (found_exit)
+             return false;
+           found_exit = true;
+           exit_count += get_exit_count (e);
+         }
+
+      bb = internal_edge->dest;
+    }
+
+  /* Punt if any exit edge had an uninitialized count.  */
+  if (!exit_count.initialized_p ())
+    return false;
You already early rturn once you hit bb with uninitialized count, so
perhaps you can move this check just after call of get_exit_count?

+      const profile_count new_exit_count = get_exit_count (exit_edge);
+      profile_probability new_exit_prob;
+      if (new_block_count.nonzero_p ())
+       new_exit_prob = new_exit_count.probability_in (new_block_count);

If new_exit_count > new_block_count probability_in will return 1.  I
guess there is not much to do, but pehraps logging inconsistency into
dump is not a bad idea here.

+      else
+       {
+         /* NEW_BLOCK_COUNT is zero, so the only way we can make the profile
+            consistent is if NEW_EXIT_COUNT is zero too.  */
+         if (dump_file && new_exit_count.nonzero_p ())
+           fprintf (dump_file,
+                    ";; flow_scale_loop_freqs wants non-zero exit count "
+                    "but bb count is zero/uninit: profile is inconsistent\n");
+
+         /* Arbitrarily set the exit probability to 0.  */
+         new_exit_prob = profile_probability::never ();

never is kind of strong hint to optimize the other patch (it has
RELIABLE reliability). Since we have no info I would just keep the
probability which was there before.
+       }

Patch is OK with these changes.

Honza

Reply via email to