On April 13, 2016 7:34:36 PM GMT+02:00, Jakub Jelinek <[email protected]> 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 <[email protected]>
>
> 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