Message ID | 20120102221403.GT18937@tyan-ft48-01.lab.bos.redhat.com |
---|---|
State | New |
Headers | show |
On Mon, 2 Jan 2012, Jakub Jelinek wrote: > Hi! > > When gimple_ic is changing an indirect call into > if (cond) > direct_call (); > else > (*indirect_call) () > and the indirect_call is not noreturn, but direct_call is > noreturn, we ICE during checking after profile, because the noreturn > call still has lhs set and edges that it shouldn't have. > > The following patch fixes, it, bootstrapped/regtested on x86_64-linux > and i686-linux, ok for trunk? Ok. Thanks, Richard. > 2012-01-02 Jakub Jelinek <jakub@redhat.com> > > PR tree-optimization/51719 > * value-prof.c (gimple_ic): When indirect call isn't noreturn, > but direct call is, clear direct call's lhs and don't add fallthrough > edge from dcall_bb to join_bb and PHIs. > > * g++.dg/tree-prof/pr51719.C: New test. > > --- gcc/value-prof.c.jj 2011-08-18 08:36:00.000000000 +0200 > +++ gcc/value-prof.c 2012-01-02 19:01:33.760867971 +0100 > @@ -1149,7 +1149,7 @@ gimple_ic (gimple icall_stmt, struct cgr > tree optype = build_pointer_type (void_type_node); > edge e_cd, e_ci, e_di, e_dj = NULL, e_ij; > gimple_stmt_iterator gsi; > - int lp_nr; > + int lp_nr, dflags; > > cond_bb = gimple_bb (icall_stmt); > gsi = gsi_for_stmt (icall_stmt); > @@ -1176,6 +1176,9 @@ gimple_ic (gimple icall_stmt, struct cgr > update_stmt (icall_stmt); > dcall_stmt = gimple_copy (icall_stmt); > gimple_call_set_fndecl (dcall_stmt, direct_call->decl); > + dflags = flags_from_decl_or_type (direct_call->decl); > + if ((dflags & ECF_NORETURN) != 0) > + gimple_call_set_lhs (dcall_stmt, NULL_TREE); > gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT); > > /* Fix CFG. */ > @@ -1220,17 +1223,23 @@ gimple_ic (gimple icall_stmt, struct cgr > > 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; > + if ((dflags & ECF_NORETURN) != 0) > + e_ij->count = all; > + else > + { > + e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU); > + e_dj->probability = REG_BR_PROB_BASE; > + e_dj->count = count; > > + 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) > - && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME) > + && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME > + && (dflags & ECF_NORETURN) == 0) > { > tree result = gimple_call_lhs (icall_stmt); > gimple phi = create_phi_node (result, join_bb); > --- gcc/testsuite/g++.dg/tree-prof/pr51719.C.jj 2012-01-02 19:11:27.633358952 +0100 > +++ gcc/testsuite/g++.dg/tree-prof/pr51719.C 2012-01-02 19:12:27.797004399 +0100 > @@ -0,0 +1,27 @@ > +// PR tree-optimization/51719 > +// { dg-options "-O -fpartial-inlining" } > + > +int > +bar (void) > +{ > + throw 1; > +} > + > +int __attribute__ ((noinline, noclone)) > +foo (int (*f) (void)) > +{ > + try > + { > + return (*f) (); > + } > + catch (...) > + { > + } > + return 0; > +} > + > +int > +main () > +{ > + return foo (bar); > +} > > Jakub > >
--- gcc/value-prof.c.jj 2011-08-18 08:36:00.000000000 +0200 +++ gcc/value-prof.c 2012-01-02 19:01:33.760867971 +0100 @@ -1149,7 +1149,7 @@ gimple_ic (gimple icall_stmt, struct cgr tree optype = build_pointer_type (void_type_node); edge e_cd, e_ci, e_di, e_dj = NULL, e_ij; gimple_stmt_iterator gsi; - int lp_nr; + int lp_nr, dflags; cond_bb = gimple_bb (icall_stmt); gsi = gsi_for_stmt (icall_stmt); @@ -1176,6 +1176,9 @@ gimple_ic (gimple icall_stmt, struct cgr update_stmt (icall_stmt); dcall_stmt = gimple_copy (icall_stmt); gimple_call_set_fndecl (dcall_stmt, direct_call->decl); + dflags = flags_from_decl_or_type (direct_call->decl); + if ((dflags & ECF_NORETURN) != 0) + gimple_call_set_lhs (dcall_stmt, NULL_TREE); gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT); /* Fix CFG. */ @@ -1220,17 +1223,23 @@ gimple_ic (gimple icall_stmt, struct cgr 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; + if ((dflags & ECF_NORETURN) != 0) + e_ij->count = all; + else + { + e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU); + e_dj->probability = REG_BR_PROB_BASE; + e_dj->count = count; + 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) - && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME) + && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME + && (dflags & ECF_NORETURN) == 0) { tree result = gimple_call_lhs (icall_stmt); gimple phi = create_phi_node (result, join_bb); --- gcc/testsuite/g++.dg/tree-prof/pr51719.C.jj 2012-01-02 19:11:27.633358952 +0100 +++ gcc/testsuite/g++.dg/tree-prof/pr51719.C 2012-01-02 19:12:27.797004399 +0100 @@ -0,0 +1,27 @@ +// PR tree-optimization/51719 +// { dg-options "-O -fpartial-inlining" } + +int +bar (void) +{ + throw 1; +} + +int __attribute__ ((noinline, noclone)) +foo (int (*f) (void)) +{ + try + { + return (*f) (); + } + catch (...) + { + } + return 0; +} + +int +main () +{ + return foo (bar); +}