On April 13, 2016 7:34:36 PM GMT+02:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >If the nothrow pass (which is GIMPLE, not IPA pass) determines that the >current function can't throw externally, it marks it nothrow. >But it fails to adjust self-recursive calls, which might change because >of >that from possibly throwing to not being able to throw, so we need to >cleanup the EH region, purge dead eh edges and adjust CFG if needed. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > >2016-04-13 Jakub Jelinek <ja...@redhat.com> > > PR c++/70641 > * ipa-pure-const.c (pass_nothrow::execute): Call maybe_clean_eh_stmt > on all recursive call stmts. Return TODO_cleanup_cfg if any dead > eh edges have been purged. > > * g++.dg/opt/pr70641.C: New test. > >--- gcc/ipa-pure-const.c.jj 2016-04-13 15:53:01.051799840 +0200 >+++ gcc/ipa-pure-const.c 2016-04-13 16:03:10.715556547 +0200 >@@ -1956,10 +1956,28 @@ pass_nothrow::execute (function *) > } > > node->set_nothrow_flag (true); >+ >+ bool cfg_changed = false; >+ if (self_recursive_p (node)) >+ FOR_EACH_BB_FN (this_block, cfun) >+ for (gimple_stmt_iterator gsi = gsi_start_bb (this_block); >+ !gsi_end_p (gsi); >+ gsi_next (&gsi))
I think it's enough to look at last_stmt. OK with that change. Richard. >+ if (is_gimple_call (gsi_stmt (gsi))) >+ { >+ gimple *g = gsi_stmt (gsi); >+ tree callee_t = gimple_call_fndecl (g); >+ if (callee_t >+ && recursive_call_p (current_function_decl, callee_t) >+ && maybe_clean_eh_stmt (g) >+ && gimple_purge_dead_eh_edges (gimple_bb (g))) >+ cfg_changed = true; >+ } >+ > if (dump_file) > fprintf (dump_file, "Function found to be nothrow: %s\n", > current_function_name ()); >- return 0; >+ return cfg_changed ? TODO_cleanup_cfg : 0; > } > > } // anon namespace >--- gcc/testsuite/g++.dg/opt/pr70641.C.jj 2016-04-13 16:01:16.381102468 >+0200 >+++ gcc/testsuite/g++.dg/opt/pr70641.C 2016-04-13 16:01:16.381102468 >+0200 >@@ -0,0 +1,10 @@ >+// PR c++/70641 >+// { dg-do compile } >+// { dg-options "-O2" } >+ >+void >+foo () >+{ >+ try { foo (); } >+ catch (...) { __builtin_abort (); } >+} > > Jakub