[PATCH] Fix -fprofile-use optimization of a noreturn indirect call (PR gcov-profile/49299)

Richard Guenther richard.guenther@gmail.com
Tue Jun 7 09:38:00 GMT 2011


On Mon, Jun 6, 2011 at 7:58 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> When an indirect noreturn call has a likely call target, value-prof.c
> ICEs on it, as there is no fallthru edge after the call (nor a join bb).
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
> ok for trunk/4.6?

Ok.

Thanks,
Richard.

> 2011-06-06  Jakub Jelinek  <jakub@redhat.com>
>
>        PR gcov-profile/49299
>        * value-prof.c (gimple_ic): Don't assume icall has
>        a fallthru edge.
>
>        * gcc.dg/tree-prof/pr49299-1.c: New test.
>        * gcc.dg/tree-prof/pr49299-2.c: New test.
>
> --- gcc/value-prof.c.jj 2011-05-02 18:39:28.000000000 +0200
> +++ gcc/value-prof.c    2011-06-06 12:37:30.000000000 +0200
> @@ -1145,9 +1145,9 @@ gimple_ic (gimple icall_stmt, struct cgr
>  {
>   gimple dcall_stmt, load_stmt, cond_stmt;
>   tree tmp0, tmp1, tmpv, tmp;
> -  basic_block cond_bb, dcall_bb, icall_bb, join_bb;
> +  basic_block cond_bb, dcall_bb, icall_bb, join_bb = NULL;
>   tree optype = build_pointer_type (void_type_node);
> -  edge e_cd, e_ci, e_di, e_dj, e_ij;
> +  edge e_cd, e_ci, e_di, e_dj = NULL, e_ij;
>   gimple_stmt_iterator gsi;
>   int lp_nr;
>
> @@ -1194,12 +1194,19 @@ gimple_ic (gimple icall_stmt, struct cgr
>   else
>     {
>       e_ij = find_fallthru_edge (icall_bb->succs);
> -      e_ij->probability = REG_BR_PROB_BASE;
> -      e_ij->count = all - count;
> -      e_ij = single_pred_edge (split_edge (e_ij));
> +      /* The indirect call might be noreturn.  */
> +      if (e_ij != NULL)
> +       {
> +         e_ij->probability = REG_BR_PROB_BASE;
> +         e_ij->count = all - count;
> +         e_ij = single_pred_edge (split_edge (e_ij));
> +       }
> +    }
> +  if (e_ij != NULL)
> +    {
> +      join_bb = e_ij->dest;
> +      join_bb->count = all;
>     }
> -  join_bb = e_ij->dest;
> -  join_bb->count = all;
>
>   e_cd->flags = (e_cd->flags & ~EDGE_FALLTHRU) | EDGE_TRUE_VALUE;
>   e_cd->probability = prob;
> @@ -1211,12 +1218,15 @@ gimple_ic (gimple icall_stmt, struct cgr
>
>   remove_edge (e_di);
>
> -  e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
> -  e_dj->probability = REG_BR_PROB_BASE;
> -  e_dj->count = count;
> +  if (e_ij != NULL)
> +    {
> +      e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
> +      e_dj->probability = REG_BR_PROB_BASE;
> +      e_dj->count = count;
>
> -  e_ij->probability = REG_BR_PROB_BASE;
> -  e_ij->count = all - count;
> +      e_ij->probability = REG_BR_PROB_BASE;
> +      e_ij->count = all - count;
> +    }
>
>   /* Insert PHI node for the call result if necessary.  */
>   if (gimple_call_lhs (icall_stmt)
> --- gcc/testsuite/gcc.dg/tree-prof/pr49299-1.c.jj       2011-06-06 11:34:58.000000000 +0200
> +++ gcc/testsuite/gcc.dg/tree-prof/pr49299-1.c  2011-06-06 11:34:51.000000000 +0200
> @@ -0,0 +1,34 @@
> +/* { dg-options "-O2" } */
> +
> +__attribute__((noreturn)) void (*fn) (void);
> +
> +volatile int v;
> +
> +__attribute__((noreturn)) void
> +fn0 (void)
> +{
> +  __builtin_exit (0);
> +}
> +
> +__attribute__((noreturn)) void
> +fn1 (void)
> +{
> +  __builtin_exit (1);
> +}
> +
> +__attribute__((noinline, noclone)) void
> +setfn (__attribute__((noreturn)) void (*x) (void))
> +{
> +  fn = x;
> +}
> +
> +int
> +main ()
> +{
> +  int i;
> +  if (v < 1)
> +    setfn (fn0);
> +  else
> +    setfn (fn1);
> +  fn ();
> +}
> --- gcc/testsuite/gcc.dg/tree-prof/pr49299-2.c.jj       2011-06-06 12:46:25.000000000 +0200
> +++ gcc/testsuite/gcc.dg/tree-prof/pr49299-2.c  2011-06-06 12:39:15.000000000 +0200
> @@ -0,0 +1,34 @@
> +/* { dg-options "-O2" } */
> +
> +void (*fn) (void);
> +
> +volatile int v;
> +
> +__attribute__((noreturn)) void
> +fn0 (void)
> +{
> +  __builtin_exit (0);
> +}
> +
> +void
> +fn1 (void)
> +{
> +}
> +
> +__attribute__((noinline, noclone)) void
> +setfn (void (*x) (void))
> +{
> +  fn = x;
> +}
> +
> +int
> +main ()
> +{
> +  int i;
> +  if (v < 1)
> +    setfn (fn0);
> +  else
> +    setfn (fn1);
> +  fn ();
> +  return 0;
> +}
>
>        Jakub
>



More information about the Gcc-patches mailing list