Message ID | 20110606175820.GX17079@tyan-ft48-01.lab.bos.redhat.com |
---|---|
State | New |
Headers | show |
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 >
--- 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; +}