diff mbox series

Add a fun parameter to three stmt_could_throw... functions

Message ID ri6ftx0crye.fsf@suse.cz
State New
Headers show
Series Add a fun parameter to three stmt_could_throw... functions | expand

Commit Message

Martin Jambor Oct. 20, 2018, 7:56 p.m. UTC
Hi,

This long patch only does one simple thing, adds an explicit function
parameter to predicates stmt_could_throw_p, stmt_can_throw_external
and stmt_can_throw_internal.

My motivation was ability to use stmt_can_throw_external in IPA
analysis phase without the need to push cfun.  As I have discovered,
we were already doing that in cgraph.c, which this patch avoids as
well.  In the process, I had to add a struct function parameter to
stmt_could_throw_p and decided to also change the interface of
stmt_can_throw_internal just for the sake of some minimal consistency.

In the process I have discovered that calling method
cgraph_node::create_version_clone_with_body (used by ipa-split,
ipa-sra, OMP simd and multiple_target) leads to calls of
stmt_can_throw_external with NULL cfun.  I have worked around this by
making stmt_can_throw_external and stmt_could_throw_p gracefully
accept NULL and just be pessimistic in that case.  The problem with
fixing this in a better way is that struct function for the clone is
created after cloning edges where we attempt to push the yet not
existing cfun, and moving it before would require a bit of surgery in
tree-inline.c.  A slightly hackish but simpler fix might be to
explicitely pass the "old" function to symbol_table::create_edge
because it should be just as good at that moment.  In any event, that
is a topic for another patch.

I believe that currently we incorrectly implicitly use cfun in
maybe_clean_eh_stmt_fn and maybe_duplicate_eh_stmt_fn, both in
tree-eh.c, and so I have fixed these cases too.  The bulk of other
changes is just mechanical adding of cfun to all users.

Bootstrapped and tested on x86_64-linux (also with extra NULLing and
restoring cfun to double check it is not used in a place I missed), OK
for trunk?

Thanks,

Martin

2018-10-20  Martin Jambor  <mjambor@suse.cz>

	* tree-eh.h (stmt_could_throw_p): Add function parameter.
	(stmt_can_throw_external): Likewise.
	(stmt_can_throw_internal): Likewise.
	* tree-eh.c (lower_eh_constructs_2): Pass cfun to stmt_could_throw_p.
	(lower_eh_constructs_2): Likewise.
	(stmt_could_throw_p): Add fun parameter, use it instead of cfun.
	(stmt_can_throw_external): Likewise.
	(stmt_can_throw_internal): Likewise.
	(maybe_clean_eh_stmt_fn): Pass cfun to stmt_could_throw_p.
	(maybe_clean_or_replace_eh_stmt): Pass cfun to stmt_could_throw_p.
	(maybe_duplicate_eh_stmt_fn): Pass new_fun to stmt_could_throw_p.
	(maybe_duplicate_eh_stmt): Pass cfun to stmt_could_throw_p.
	(pass_lower_eh_dispatch::execute): Pass cfun to
	stmt_can_throw_external.
	(cleanup_empty_eh): Likewise.
	(verify_eh_edges): Pass cfun to stmt_could_throw_p.
	* cgraph.c (cgraph_edge::set_call_stmt): Pass a function to
	stmt_can_throw_external instead of pushing it to cfun.
	(symbol_table::create_edge): Likewise.
	* gimple-fold.c (fold_builtin_atomic_compare_exchange): Pass cfun to
	stmt_can_throw_internal.
	* gimple-ssa-evrp.c (evrp_dom_walker::before_dom_children): Pass cfun
	to stmt_could_throw_p.
	* gimple-ssa-store-merging.c (handled_load): Pass cfun to
	stmt_can_throw_internal.
	(pass_store_merging::execute): Likewise.
	* gimple-ssa-strength-reduction.c
	(find_candidates_dom_walker::before_dom_children): Pass cfun to
	stmt_could_throw_p.
	* gimplify-me.c (gimple_regimplify_operands): Pass cfun to
	stmt_can_throw_internal.
	* ipa-pure-const.c (check_call): Pass cfun to stmt_could_throw_p and
	to stmt_can_throw_external.
	(check_stmt): Pass cfun to stmt_could_throw_p.
	(check_stmt): Pass cfun to stmt_can_throw_external.
	(pass_nothrow::execute): Likewise.
	* trans-mem.c (expand_call_tm): Pass cfun to stmt_can_throw_internal.
	* tree-cfg.c (is_ctrl_altering_stmt): Pass cfun to
	stmt_can_throw_internal.
	(verify_gimple_in_cfg): Pass cfun to stmt_could_throw_p.
	(stmt_can_terminate_bb_p): Pass cfun to stmt_can_throw_external.
	(gimple_purge_dead_eh_edges): Pass cfun to stmt_can_throw_internal.
	* tree-complex.c (expand_complex_libcall): Pass cfun to
	stmt_could_throw_p and to stmt_can_throw_internal.
	(expand_complex_multiplication): Pass cfun to stmt_can_throw_internal.
	* tree-inline.c (copy_edges_for_bb): Likewise.
	(maybe_move_debug_stmts_to_successors): Likewise.
	* tree-outof-ssa.c (ssa_is_replaceable_p): Pass cfun to
	stmt_could_throw_p.
	* tree-parloops.c (oacc_entry_exit_ok_1): Likewise.
	* tree-sra.c (scan_function): Pass cfun to stmt_can_throw_external.
	* tree-ssa-alias.c (stmt_kills_ref_p): Pass cfun to
	stmt_can_throw_internal.
	* tree-ssa-ccp.c (optimize_atomic_bit_test_and): Likewise.
	* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Pass cfun to
	stmt_could_throw_p.
	(mark_aliased_reaching_defs_necessary_1): Pass cfun to
	stmt_can_throw_internal.
	* tree-ssa-forwprop.c (pass_forwprop::execute): Likewise.
	* tree-ssa-loop-im.c (movement_possibility): Pass cfun to
	stmt_could_throw_p.
	* tree-ssa-loop-ivopts.c (find_givs_in_stmt_scev): Likewise.
	(add_autoinc_candidates): Pass cfun to stmt_can_throw_internal.
	* tree-ssa-math-opts.c (pass_cse_reciprocals::execute): Likewise.
	(convert_mult_to_fma_1): Likewise.
	(convert_to_divmod): Likewise.
	* tree-ssa-phiprop.c (propagate_with_phi): Likewise.
	* tree-ssa-pre.c (compute_avail): Pass cfun to stmt_could_throw_p.
	* tree-ssa-propagate.c
	(substitute_and_fold_dom_walker::before_dom_children): Likewise.
	* tree-ssa-reassoc.c (suitable_cond_bb): Likewise.
	(maybe_optimize_range_tests): Likewise.
	(linearize_expr_tree): Likewise.
	(reassociate_bb): Likewise.
	* tree-ssa-sccvn.c (copy_reference_ops_from_call): Likewise.
	* tree-ssa-scopedtables.c (hashable_expr_equal_p): Likewise.
	* tree-ssa-strlen.c (adjust_last_stmt): Likewise.
	(handle_char_store): Likewise.
	* tree-vect-data-refs.c (vect_find_stmt_data_reference): Pass cfun to
	stmt_can_throw_internal.
	* tree-vect-patterns.c (check_bool_pattern): Pass cfun to
	stmt_could_throw_p.
	* tree-vect-stmts.c (vect_finish_stmt_generation_1): Likewise.
	(vectorizable_call): Pass cfun to stmt_can_throw_internal.
	(vectorizable_simd_clone_call): Likewise.
	* value-prof.c (gimple_ic): Pass cfun to stmt_could_throw_p.
	(gimple_stringop_fixed_value): Likewise.
---
 gcc/cgraph.c                        | 10 +++---
 gcc/gimple-fold.c                   |  2 +-
 gcc/gimple-ssa-evrp.c               |  2 +-
 gcc/gimple-ssa-store-merging.c      |  4 +--
 gcc/gimple-ssa-strength-reduction.c |  2 +-
 gcc/gimplify-me.c                   |  2 +-
 gcc/ipa-pure-const.c                | 10 +++---
 gcc/trans-mem.c                     |  2 +-
 gcc/tree-cfg.c                      |  8 ++---
 gcc/tree-complex.c                  |  6 ++--
 gcc/tree-eh.c                       | 52 ++++++++++++++++-------------
 gcc/tree-eh.h                       |  6 ++--
 gcc/tree-inline.c                   |  4 +--
 gcc/tree-outof-ssa.c                |  2 +-
 gcc/tree-parloops.c                 |  2 +-
 gcc/tree-sra.c                      |  2 +-
 gcc/tree-ssa-alias.c                |  2 +-
 gcc/tree-ssa-ccp.c                  |  2 +-
 gcc/tree-ssa-dce.c                  |  4 +--
 gcc/tree-ssa-forwprop.c             |  2 +-
 gcc/tree-ssa-loop-im.c              |  2 +-
 gcc/tree-ssa-loop-ivopts.c          |  4 +--
 gcc/tree-ssa-math-opts.c            | 11 +++---
 gcc/tree-ssa-phiprop.c              |  2 +-
 gcc/tree-ssa-pre.c                  |  2 +-
 gcc/tree-ssa-propagate.c            |  2 +-
 gcc/tree-ssa-reassoc.c              | 10 +++---
 gcc/tree-ssa-sccvn.c                |  2 +-
 gcc/tree-ssa-scopedtables.c         |  2 +-
 gcc/tree-ssa-strlen.c               |  4 +--
 gcc/tree-vect-data-refs.c           |  2 +-
 gcc/tree-vect-patterns.c            |  2 +-
 gcc/tree-vect-stmts.c               |  6 ++--
 gcc/value-prof.c                    |  8 ++---
 34 files changed, 94 insertions(+), 91 deletions(-)

Comments

Richard Biener Oct. 22, 2018, 7:10 a.m. UTC | #1
On Sat, 20 Oct 2018, Martin Jambor wrote:

> Hi,
> 
> This long patch only does one simple thing, adds an explicit function
> parameter to predicates stmt_could_throw_p, stmt_can_throw_external
> and stmt_can_throw_internal.
> 
> My motivation was ability to use stmt_can_throw_external in IPA
> analysis phase without the need to push cfun.  As I have discovered,
> we were already doing that in cgraph.c, which this patch avoids as
> well.  In the process, I had to add a struct function parameter to
> stmt_could_throw_p and decided to also change the interface of
> stmt_can_throw_internal just for the sake of some minimal consistency.
> 
> In the process I have discovered that calling method
> cgraph_node::create_version_clone_with_body (used by ipa-split,
> ipa-sra, OMP simd and multiple_target) leads to calls of
> stmt_can_throw_external with NULL cfun.  I have worked around this by
> making stmt_can_throw_external and stmt_could_throw_p gracefully
> accept NULL and just be pessimistic in that case.  The problem with
> fixing this in a better way is that struct function for the clone is
> created after cloning edges where we attempt to push the yet not
> existing cfun, and moving it before would require a bit of surgery in
> tree-inline.c.  A slightly hackish but simpler fix might be to
> explicitely pass the "old" function to symbol_table::create_edge
> because it should be just as good at that moment.

I think that's the best and reasonable thing to do.

> In any event, that
> is a topic for another patch.

Fine with me - handling NULL fn conservatively is OK.

> I believe that currently we incorrectly implicitly use cfun in
> maybe_clean_eh_stmt_fn and maybe_duplicate_eh_stmt_fn, both in
> tree-eh.c, and so I have fixed these cases too.  The bulk of other
> changes is just mechanical adding of cfun to all users.
> 
> Bootstrapped and tested on x86_64-linux (also with extra NULLing and
> restoring cfun to double check it is not used in a place I missed), OK
> for trunk?

OK.

Thanks,
Richard.

> Thanks,
> 
> Martin
> 
> 2018-10-20  Martin Jambor  <mjambor@suse.cz>
> 
> 	* tree-eh.h (stmt_could_throw_p): Add function parameter.
> 	(stmt_can_throw_external): Likewise.
> 	(stmt_can_throw_internal): Likewise.
> 	* tree-eh.c (lower_eh_constructs_2): Pass cfun to stmt_could_throw_p.
> 	(lower_eh_constructs_2): Likewise.
> 	(stmt_could_throw_p): Add fun parameter, use it instead of cfun.
> 	(stmt_can_throw_external): Likewise.
> 	(stmt_can_throw_internal): Likewise.
> 	(maybe_clean_eh_stmt_fn): Pass cfun to stmt_could_throw_p.
> 	(maybe_clean_or_replace_eh_stmt): Pass cfun to stmt_could_throw_p.
> 	(maybe_duplicate_eh_stmt_fn): Pass new_fun to stmt_could_throw_p.
> 	(maybe_duplicate_eh_stmt): Pass cfun to stmt_could_throw_p.
> 	(pass_lower_eh_dispatch::execute): Pass cfun to
> 	stmt_can_throw_external.
> 	(cleanup_empty_eh): Likewise.
> 	(verify_eh_edges): Pass cfun to stmt_could_throw_p.
> 	* cgraph.c (cgraph_edge::set_call_stmt): Pass a function to
> 	stmt_can_throw_external instead of pushing it to cfun.
> 	(symbol_table::create_edge): Likewise.
> 	* gimple-fold.c (fold_builtin_atomic_compare_exchange): Pass cfun to
> 	stmt_can_throw_internal.
> 	* gimple-ssa-evrp.c (evrp_dom_walker::before_dom_children): Pass cfun
> 	to stmt_could_throw_p.
> 	* gimple-ssa-store-merging.c (handled_load): Pass cfun to
> 	stmt_can_throw_internal.
> 	(pass_store_merging::execute): Likewise.
> 	* gimple-ssa-strength-reduction.c
> 	(find_candidates_dom_walker::before_dom_children): Pass cfun to
> 	stmt_could_throw_p.
> 	* gimplify-me.c (gimple_regimplify_operands): Pass cfun to
> 	stmt_can_throw_internal.
> 	* ipa-pure-const.c (check_call): Pass cfun to stmt_could_throw_p and
> 	to stmt_can_throw_external.
> 	(check_stmt): Pass cfun to stmt_could_throw_p.
> 	(check_stmt): Pass cfun to stmt_can_throw_external.
> 	(pass_nothrow::execute): Likewise.
> 	* trans-mem.c (expand_call_tm): Pass cfun to stmt_can_throw_internal.
> 	* tree-cfg.c (is_ctrl_altering_stmt): Pass cfun to
> 	stmt_can_throw_internal.
> 	(verify_gimple_in_cfg): Pass cfun to stmt_could_throw_p.
> 	(stmt_can_terminate_bb_p): Pass cfun to stmt_can_throw_external.
> 	(gimple_purge_dead_eh_edges): Pass cfun to stmt_can_throw_internal.
> 	* tree-complex.c (expand_complex_libcall): Pass cfun to
> 	stmt_could_throw_p and to stmt_can_throw_internal.
> 	(expand_complex_multiplication): Pass cfun to stmt_can_throw_internal.
> 	* tree-inline.c (copy_edges_for_bb): Likewise.
> 	(maybe_move_debug_stmts_to_successors): Likewise.
> 	* tree-outof-ssa.c (ssa_is_replaceable_p): Pass cfun to
> 	stmt_could_throw_p.
> 	* tree-parloops.c (oacc_entry_exit_ok_1): Likewise.
> 	* tree-sra.c (scan_function): Pass cfun to stmt_can_throw_external.
> 	* tree-ssa-alias.c (stmt_kills_ref_p): Pass cfun to
> 	stmt_can_throw_internal.
> 	* tree-ssa-ccp.c (optimize_atomic_bit_test_and): Likewise.
> 	* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Pass cfun to
> 	stmt_could_throw_p.
> 	(mark_aliased_reaching_defs_necessary_1): Pass cfun to
> 	stmt_can_throw_internal.
> 	* tree-ssa-forwprop.c (pass_forwprop::execute): Likewise.
> 	* tree-ssa-loop-im.c (movement_possibility): Pass cfun to
> 	stmt_could_throw_p.
> 	* tree-ssa-loop-ivopts.c (find_givs_in_stmt_scev): Likewise.
> 	(add_autoinc_candidates): Pass cfun to stmt_can_throw_internal.
> 	* tree-ssa-math-opts.c (pass_cse_reciprocals::execute): Likewise.
> 	(convert_mult_to_fma_1): Likewise.
> 	(convert_to_divmod): Likewise.
> 	* tree-ssa-phiprop.c (propagate_with_phi): Likewise.
> 	* tree-ssa-pre.c (compute_avail): Pass cfun to stmt_could_throw_p.
> 	* tree-ssa-propagate.c
> 	(substitute_and_fold_dom_walker::before_dom_children): Likewise.
> 	* tree-ssa-reassoc.c (suitable_cond_bb): Likewise.
> 	(maybe_optimize_range_tests): Likewise.
> 	(linearize_expr_tree): Likewise.
> 	(reassociate_bb): Likewise.
> 	* tree-ssa-sccvn.c (copy_reference_ops_from_call): Likewise.
> 	* tree-ssa-scopedtables.c (hashable_expr_equal_p): Likewise.
> 	* tree-ssa-strlen.c (adjust_last_stmt): Likewise.
> 	(handle_char_store): Likewise.
> 	* tree-vect-data-refs.c (vect_find_stmt_data_reference): Pass cfun to
> 	stmt_can_throw_internal.
> 	* tree-vect-patterns.c (check_bool_pattern): Pass cfun to
> 	stmt_could_throw_p.
> 	* tree-vect-stmts.c (vect_finish_stmt_generation_1): Likewise.
> 	(vectorizable_call): Pass cfun to stmt_can_throw_internal.
> 	(vectorizable_simd_clone_call): Likewise.
> 	* value-prof.c (gimple_ic): Pass cfun to stmt_could_throw_p.
> 	(gimple_stringop_fixed_value): Likewise.
> ---
>  gcc/cgraph.c                        | 10 +++---
>  gcc/gimple-fold.c                   |  2 +-
>  gcc/gimple-ssa-evrp.c               |  2 +-
>  gcc/gimple-ssa-store-merging.c      |  4 +--
>  gcc/gimple-ssa-strength-reduction.c |  2 +-
>  gcc/gimplify-me.c                   |  2 +-
>  gcc/ipa-pure-const.c                | 10 +++---
>  gcc/trans-mem.c                     |  2 +-
>  gcc/tree-cfg.c                      |  8 ++---
>  gcc/tree-complex.c                  |  6 ++--
>  gcc/tree-eh.c                       | 52 ++++++++++++++++-------------
>  gcc/tree-eh.h                       |  6 ++--
>  gcc/tree-inline.c                   |  4 +--
>  gcc/tree-outof-ssa.c                |  2 +-
>  gcc/tree-parloops.c                 |  2 +-
>  gcc/tree-sra.c                      |  2 +-
>  gcc/tree-ssa-alias.c                |  2 +-
>  gcc/tree-ssa-ccp.c                  |  2 +-
>  gcc/tree-ssa-dce.c                  |  4 +--
>  gcc/tree-ssa-forwprop.c             |  2 +-
>  gcc/tree-ssa-loop-im.c              |  2 +-
>  gcc/tree-ssa-loop-ivopts.c          |  4 +--
>  gcc/tree-ssa-math-opts.c            | 11 +++---
>  gcc/tree-ssa-phiprop.c              |  2 +-
>  gcc/tree-ssa-pre.c                  |  2 +-
>  gcc/tree-ssa-propagate.c            |  2 +-
>  gcc/tree-ssa-reassoc.c              | 10 +++---
>  gcc/tree-ssa-sccvn.c                |  2 +-
>  gcc/tree-ssa-scopedtables.c         |  2 +-
>  gcc/tree-ssa-strlen.c               |  4 +--
>  gcc/tree-vect-data-refs.c           |  2 +-
>  gcc/tree-vect-patterns.c            |  2 +-
>  gcc/tree-vect-stmts.c               |  6 ++--
>  gcc/value-prof.c                    |  8 ++---
>  34 files changed, 94 insertions(+), 91 deletions(-)
> 
> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> index 8a03f3d6828..48bab9f2749 100644
> --- a/gcc/cgraph.c
> +++ b/gcc/cgraph.c
> @@ -815,9 +815,8 @@ cgraph_edge::set_call_stmt (gcall *new_stmt, bool update_speculative)
>        e = make_direct (new_callee);
>      }
>  
> -  push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
> -  e->can_throw_external = stmt_can_throw_external (new_stmt);
> -  pop_cfun ();
> +  function *fun = DECL_STRUCT_FUNCTION (e->caller->decl);
> +  e->can_throw_external = stmt_can_throw_external (fun, new_stmt);
>    if (e->caller->call_site_hash)
>      cgraph_add_edge_to_call_site_hash (e);
>  }
> @@ -870,10 +869,9 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
>    edge->count = count;
>  
>    edge->call_stmt = call_stmt;
> -  push_cfun (DECL_STRUCT_FUNCTION (caller->decl));
>    edge->can_throw_external
> -    = call_stmt ? stmt_can_throw_external (call_stmt) : false;
> -  pop_cfun ();
> +    = call_stmt ? stmt_can_throw_external (DECL_STRUCT_FUNCTION (caller->decl),
> +					   call_stmt) : false;
>    if (call_stmt
>        && callee && callee->decl
>        && !gimple_check_call_matching_types (call_stmt, callee->decl,
> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
> index fe6bc08bdd9..e862b1a1d4c 100644
> --- a/gcc/gimple-fold.c
> +++ b/gcc/gimple-fold.c
> @@ -4023,7 +4023,7 @@ fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *gsi)
>    gimple_set_vuse (g, gimple_vuse (stmt));
>    SSA_NAME_DEF_STMT (gimple_vdef (g)) = g;
>    tree oldlhs = gimple_call_lhs (stmt);
> -  if (stmt_can_throw_internal (stmt))
> +  if (stmt_can_throw_internal (cfun, stmt))
>      {
>        throws = true;
>        e = find_fallthru_edge (gsi_bb (*gsi)->succs);
> diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
> index 50e8adc1aad..7d952765c5a 100644
> --- a/gcc/gimple-ssa-evrp.c
> +++ b/gcc/gimple-ssa-evrp.c
> @@ -164,7 +164,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
>  	      if ((vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE)
>  		  && (val = value_range_constant_singleton (vr))
>  		  && may_propagate_copy (output, val)
> -		  && !stmt_could_throw_p (stmt)
> +		  && !stmt_could_throw_p (cfun, stmt)
>  		  && !gimple_has_side_effects (stmt))
>  		{
>  		  stmts_to_remove.safe_push (stmt);
> diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
> index 85dd5bccead..e1ddcb5e558 100644
> --- a/gcc/gimple-ssa-store-merging.c
> +++ b/gcc/gimple-ssa-store-merging.c
> @@ -4256,7 +4256,7 @@ handled_load (gimple *stmt, store_operand_info *op,
>      }
>    if (gimple_vuse (stmt)
>        && gimple_assign_load_p (stmt)
> -      && !stmt_can_throw_internal (stmt)
> +      && !stmt_can_throw_internal (cfun, stmt)
>        && !gimple_has_volatile_ops (stmt))
>      {
>        tree mem = gimple_assign_rhs1 (stmt);
> @@ -4551,7 +4551,7 @@ pass_store_merging::execute (function *fun)
>  	    }
>  
>  	  if (gimple_assign_single_p (stmt) && gimple_vdef (stmt)
> -	      && !stmt_can_throw_internal (stmt)
> +	      && !stmt_can_throw_internal (cfun, stmt)
>  	      && lhs_valid_for_store_merging_p (gimple_assign_lhs (stmt)))
>  	    process_store (stmt);
>  	  else
> diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
> index ea81adca7ea..7ed6ae7f88a 100644
> --- a/gcc/gimple-ssa-strength-reduction.c
> +++ b/gcc/gimple-ssa-strength-reduction.c
> @@ -1775,7 +1775,7 @@ find_candidates_dom_walker::before_dom_children (basic_block bb)
>      {
>        gimple *gs = gsi_stmt (gsi);
>  
> -      if (stmt_could_throw_p (gs))
> +      if (stmt_could_throw_p (cfun, gs))
>  	continue;
>  
>        if (gimple_vuse (gs) && gimple_assign_single_p (gs))
> diff --git a/gcc/gimplify-me.c b/gcc/gimplify-me.c
> index 137a5662ccf..269fe6b3bae 100644
> --- a/gcc/gimplify-me.c
> +++ b/gcc/gimplify-me.c
> @@ -273,7 +273,7 @@ gimple_regimplify_operands (gimple *stmt, gimple_stmt_iterator *gsi_p)
>  			  || !(i & (ECF_CONST | ECF_PURE)))
>  			need_temp = true;
>  		    }
> -		  if (stmt_can_throw_internal (stmt))
> +		  if (stmt_can_throw_internal (cfun, stmt))
>  		    need_temp = true;
>  		}
>  	    }
> diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
> index 66c81be23ec..1ca1d60517e 100644
> --- a/gcc/ipa-pure-const.c
> +++ b/gcc/ipa-pure-const.c
> @@ -555,9 +555,9 @@ check_call (funct_state local, gcall *call, bool ipa)
>  {
>    int flags = gimple_call_flags (call);
>    tree callee_t = gimple_call_fndecl (call);
> -  bool possibly_throws = stmt_could_throw_p (call);
> +  bool possibly_throws = stmt_could_throw_p (cfun, call);
>    bool possibly_throws_externally = (possibly_throws
> -  				     && stmt_can_throw_external (call));
> +  				     && stmt_can_throw_external (cfun, call));
>  
>    if (possibly_throws)
>      {
> @@ -770,7 +770,7 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
>  			    ipa ? check_ipa_store :  check_store);
>  
>    if (gimple_code (stmt) != GIMPLE_CALL
> -      && stmt_could_throw_p (stmt))
> +      && stmt_could_throw_p (cfun, stmt))
>      {
>        if (cfun->can_throw_non_call_exceptions)
>  	{
> @@ -778,7 +778,7 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
>  	    fprintf (dump_file, "    can throw; looping\n");
>  	  local->looping = true;
>  	}
> -      if (stmt_can_throw_external (stmt))
> +      if (stmt_can_throw_external (cfun, stmt))
>  	{
>  	  if (dump_file)
>  	    fprintf (dump_file, "    can throw externally\n");
> @@ -2307,7 +2307,7 @@ pass_nothrow::execute (function *)
>        for (gimple_stmt_iterator gsi = gsi_start_bb (this_block);
>  	   !gsi_end_p (gsi);
>  	   gsi_next (&gsi))
> -        if (stmt_can_throw_external (gsi_stmt (gsi)))
> +        if (stmt_can_throw_external (cfun, gsi_stmt (gsi)))
>  	  {
>  	    if (is_gimple_call (gsi_stmt (gsi)))
>  	      {
> diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
> index 1d4eb806202..7e4bcec4030 100644
> --- a/gcc/trans-mem.c
> +++ b/gcc/trans-mem.c
> @@ -2582,7 +2582,7 @@ expand_call_tm (struct tm_region *region,
>        gassign *assign_stmt;
>  
>        /* Remember if the call was going to throw.  */
> -      if (stmt_can_throw_internal (stmt))
> +      if (stmt_can_throw_internal (cfun, stmt))
>  	{
>  	  edge_iterator ei;
>  	  edge e;
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index 87979bc4d75..d30e4aca773 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -2720,7 +2720,7 @@ is_ctrl_altering_stmt (gimple *t)
>      }
>  
>    /* If a statement can throw, it alters control flow.  */
> -  return stmt_can_throw_internal (t);
> +  return stmt_can_throw_internal (cfun, t);
>  }
>  
>  
> @@ -5387,7 +5387,7 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
>  	    visited_throwing_stmts.add (stmt);
>  	  if (lp_nr > 0)
>  	    {
> -	      if (!stmt_could_throw_p (stmt))
> +	      if (!stmt_could_throw_p (cfun, stmt))
>  		{
>  		  if (verify_nothrow)
>  		    {
> @@ -8283,7 +8283,7 @@ stmt_can_terminate_bb_p (gimple *t)
>  
>    /* Eh exception not handled internally terminates execution of the whole
>       function.  */
> -  if (stmt_can_throw_external (t))
> +  if (stmt_can_throw_external (cfun, t))
>      return true;
>  
>    /* NORETURN and LONGJMP calls already have an edge to exit.
> @@ -8599,7 +8599,7 @@ gimple_purge_dead_eh_edges (basic_block bb)
>    edge_iterator ei;
>    gimple *stmt = last_stmt (bb);
>  
> -  if (stmt && stmt_can_throw_internal (stmt))
> +  if (stmt && stmt_can_throw_internal (cfun, stmt))
>      return false;
>  
>    for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
> diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
> index 93f274cd213..49088081bb0 100644
> --- a/gcc/tree-complex.c
> +++ b/gcc/tree-complex.c
> @@ -1010,13 +1010,13 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree type, tree ar, tree ai,
>    if (inplace_p)
>      {
>        gimple *old_stmt = gsi_stmt (*gsi);
> -      gimple_call_set_nothrow (stmt, !stmt_could_throw_p (old_stmt));
> +      gimple_call_set_nothrow (stmt, !stmt_could_throw_p (cfun, old_stmt));
>        lhs = gimple_assign_lhs (old_stmt);
>        gimple_call_set_lhs (stmt, lhs);
>        gsi_replace (gsi, stmt, true);
>  
>        type = TREE_TYPE (type);
> -      if (stmt_can_throw_internal (stmt))
> +      if (stmt_can_throw_internal (cfun, stmt))
>  	{
>  	  edge_iterator ei;
>  	  edge e;
> @@ -1134,7 +1134,7 @@ expand_complex_multiplication (gimple_stmt_iterator *gsi, tree type,
>  	  /* If optimizing for size or not at all just do a libcall.
>  	     Same if there are exception-handling edges or signaling NaNs.  */
>  	  if (optimize == 0 || optimize_bb_for_size_p (gsi_bb (*gsi))
> -	     || stmt_can_throw_internal (gsi_stmt (*gsi))
> +	     || stmt_can_throw_internal (cfun, gsi_stmt (*gsi))
>  	     || flag_signaling_nans)
>  	    {
>  	      expand_complex_libcall (gsi, type, ar, ai, br, bi,
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index fb931aa4389..1c7d9dc1d59 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -2033,7 +2033,7 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
>  	 available on the EH edge.  Only do so for statements that
>  	 potentially fall through (no noreturn calls e.g.), otherwise
>  	 this new assignment might create fake fallthru regions.  */
> -      if (stmt_could_throw_p (stmt)
> +      if (stmt_could_throw_p (cfun, stmt)
>  	  && gimple_has_lhs (stmt)
>  	  && gimple_stmt_may_fallthru (stmt)
>  	  && !tree_could_throw_p (gimple_get_lhs (stmt))
> @@ -2051,7 +2051,7 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
>  	  gsi_insert_after (gsi, s, GSI_SAME_STMT);
>  	}
>        /* Look for things that can throw exceptions, and record them.  */
> -      if (state->cur_region && stmt_could_throw_p (stmt))
> +      if (state->cur_region && stmt_could_throw_p (cfun, stmt))
>  	{
>  	  record_stmt_eh_region (state->cur_region, stmt);
>  	  note_eh_region_may_contain_throw (state->cur_region);
> @@ -2866,10 +2866,10 @@ stmt_could_throw_1_p (gassign *stmt)
>  }
>  
>  
> -/* Return true if statement STMT could throw an exception.  */
> +/* Return true if statement STMT within FUN could throw an exception.  */
>  
>  bool
> -stmt_could_throw_p (gimple *stmt)
> +stmt_could_throw_p (function *fun, gimple *stmt)
>  {
>    if (!flag_exceptions)
>      return false;
> @@ -2886,7 +2886,7 @@ stmt_could_throw_p (gimple *stmt)
>  
>      case GIMPLE_COND:
>        {
> -	if (!cfun->can_throw_non_call_exceptions)
> +	if (fun && !fun->can_throw_non_call_exceptions)
>  	  return false;
>  	gcond *cond = as_a <gcond *> (stmt);
>  	tree lhs = gimple_cond_lhs (cond);
> @@ -2896,13 +2896,13 @@ stmt_could_throw_p (gimple *stmt)
>        }
>  
>      case GIMPLE_ASSIGN:
> -      if (!cfun->can_throw_non_call_exceptions
> +      if ((fun && !fun->can_throw_non_call_exceptions)
>  	  || gimple_clobber_p (stmt))
>          return false;
>        return stmt_could_throw_1_p (as_a <gassign *> (stmt));
>  
>      case GIMPLE_ASM:
> -      if (!cfun->can_throw_non_call_exceptions)
> +      if (fun && !fun->can_throw_non_call_exceptions)
>          return false;
>        return gimple_asm_volatile_p (as_a <gasm *> (stmt));
>  
> @@ -2936,33 +2936,37 @@ tree_could_throw_p (tree t)
>    return false;
>  }
>  
> -/* Return true if STMT can throw an exception that is not caught within
> -   the current function (CFUN).  */
> +/* Return true if STMT can throw an exception that is not caught within its
> +   function FUN.  FUN can be NULL but the function is extra conservative
> +   then.  */
>  
>  bool
> -stmt_can_throw_external (gimple *stmt)
> +stmt_can_throw_external (function *fun, gimple *stmt)
>  {
>    int lp_nr;
>  
> -  if (!stmt_could_throw_p (stmt))
> +  if (!stmt_could_throw_p (fun, stmt))
>      return false;
> +  if (!fun)
> +    return true;
>  
> -  lp_nr = lookup_stmt_eh_lp (stmt);
> +  lp_nr = lookup_stmt_eh_lp_fn (fun, stmt);
>    return lp_nr == 0;
>  }
>  
> -/* Return true if STMT can throw an exception that is caught within
> -   the current function (CFUN).  */
> +/* Return true if STMT can throw an exception that is caught within its
> +   function FUN.  */
>  
>  bool
> -stmt_can_throw_internal (gimple *stmt)
> +stmt_can_throw_internal (function *fun, gimple *stmt)
>  {
>    int lp_nr;
>  
> -  if (!stmt_could_throw_p (stmt))
> +  gcc_checking_assert (fun);
> +  if (!stmt_could_throw_p (fun, stmt))
>      return false;
>  
> -  lp_nr = lookup_stmt_eh_lp (stmt);
> +  lp_nr = lookup_stmt_eh_lp_fn (fun, stmt);
>    return lp_nr > 0;
>  }
>  
> @@ -2973,7 +2977,7 @@ stmt_can_throw_internal (gimple *stmt)
>  bool
>  maybe_clean_eh_stmt_fn (struct function *ifun, gimple *stmt)
>  {
> -  if (stmt_could_throw_p (stmt))
> +  if (stmt_could_throw_p (ifun, stmt))
>      return false;
>    return remove_stmt_from_eh_lp_fn (ifun, stmt);
>  }
> @@ -2998,7 +3002,7 @@ maybe_clean_or_replace_eh_stmt (gimple *old_stmt, gimple *new_stmt)
>  
>    if (lp_nr != 0)
>      {
> -      bool new_stmt_could_throw = stmt_could_throw_p (new_stmt);
> +      bool new_stmt_could_throw = stmt_could_throw_p (cfun, new_stmt);
>  
>        if (new_stmt == old_stmt && new_stmt_could_throw)
>  	return false;
> @@ -3028,7 +3032,7 @@ maybe_duplicate_eh_stmt_fn (struct function *new_fun, gimple *new_stmt,
>  {
>    int old_lp_nr, new_lp_nr;
>  
> -  if (!stmt_could_throw_p (new_stmt))
> +  if (!stmt_could_throw_p (new_fun, new_stmt))
>      return false;
>  
>    old_lp_nr = lookup_stmt_eh_lp_fn (old_fun, old_stmt);
> @@ -3067,7 +3071,7 @@ maybe_duplicate_eh_stmt (gimple *new_stmt, gimple *old_stmt)
>  {
>    int lp_nr;
>  
> -  if (!stmt_could_throw_p (new_stmt))
> +  if (!stmt_could_throw_p (cfun, new_stmt))
>      return false;
>  
>    lp_nr = lookup_stmt_eh_lp (old_stmt);
> @@ -3862,7 +3866,7 @@ pass_lower_eh_dispatch::execute (function *fun)
>  	}
>        else if (gimple_code (last) == GIMPLE_RESX)
>  	{
> -	  if (stmt_can_throw_external (last))
> +	  if (stmt_can_throw_external (cfun, last))
>  	    optimize_clobbers (bb);
>  	  else
>  	    flags |= sink_clobbers (bb);
> @@ -4502,7 +4506,7 @@ cleanup_empty_eh (eh_landing_pad lp)
>    resx = gsi_stmt (gsi);
>    if (resx && is_gimple_resx (resx))
>      {
> -      if (stmt_can_throw_external (resx))
> +      if (stmt_can_throw_external (cfun, resx))
>  	optimize_clobbers (bb);
>        else if (sink_clobbers (bb))
>  	ret = true;
> @@ -4783,7 +4787,7 @@ verify_eh_edges (gimple *stmt)
>        return false;
>      }
>  
> -  if (!stmt_could_throw_p (stmt))
> +  if (!stmt_could_throw_p (cfun, stmt))
>      {
>        error ("BB %i last statement has incorrectly set lp", bb->index);
>        return true;
> diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h
> index 11e096c9e5f..2bd6a856bd9 100644
> --- a/gcc/tree-eh.h
> +++ b/gcc/tree-eh.h
> @@ -38,10 +38,10 @@ extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
>  extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
>  extern bool tree_could_trap_p (tree);
>  extern tree rewrite_to_non_trapping_overflow (tree);
> -extern bool stmt_could_throw_p (gimple *);
> +extern bool stmt_could_throw_p (function *, gimple *);
>  extern bool tree_could_throw_p (tree);
> -extern bool stmt_can_throw_external (gimple *);
> -extern bool stmt_can_throw_internal (gimple *);
> +extern bool stmt_can_throw_external (function *, gimple *);
> +extern bool stmt_can_throw_internal (function *, gimple *);
>  extern bool maybe_clean_eh_stmt_fn (struct function *, gimple *);
>  extern bool maybe_clean_eh_stmt (gimple *);
>  extern bool maybe_clean_or_replace_eh_stmt (gimple *, gimple *);
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index 913425394e0..297fcd70c82 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -2246,7 +2246,7 @@ copy_edges_for_bb (basic_block bb, profile_count num, profile_count den,
>           propagation can change an INDIRECT_REF which throws
>           into a COMPONENT_REF which doesn't.  If the copy
>           can throw, the original could also throw.  */
> -      can_throw = stmt_can_throw_internal (copy_stmt);
> +      can_throw = stmt_can_throw_internal (cfun, copy_stmt);
>        nonlocal_goto
>  	= (stmt_can_make_abnormal_goto (copy_stmt)
>  	   && !computed_goto_p (copy_stmt));
> @@ -2514,7 +2514,7 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
>  
>    if (gsi_end_p (si)
>        || gsi_one_before_end_p (si)
> -      || !(stmt_can_throw_internal (gsi_stmt (si))
> +      || !(stmt_can_throw_internal (cfun, gsi_stmt (si))
>  	   || stmt_can_make_abnormal_goto (gsi_stmt (si))))
>      return;
>  
> diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
> index 3f880ef7382..fca15e5f898 100644
> --- a/gcc/tree-outof-ssa.c
> +++ b/gcc/tree-outof-ssa.c
> @@ -65,7 +65,7 @@ ssa_is_replaceable_p (gimple *stmt)
>      return false;
>  
>    /* If the statement may throw an exception, it cannot be replaced.  */
> -  if (stmt_could_throw_p (stmt))
> +  if (stmt_could_throw_p (cfun, stmt))
>      return false;
>  
>    /* Punt if there is more than 1 def.  */
> diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
> index e89c8875147..5935cf40927 100644
> --- a/gcc/tree-parloops.c
> +++ b/gcc/tree-parloops.c
> @@ -3076,7 +3076,7 @@ oacc_entry_exit_ok_1 (bitmap in_loop_bbs, vec<basic_block> region_bbs,
>  	    continue;
>  	  else if (!gimple_has_side_effects (stmt)
>  		   && !gimple_could_trap_p (stmt)
> -		   && !stmt_could_throw_p (stmt)
> +		   && !stmt_could_throw_p (cfun, stmt)
>  		   && !gimple_vdef (stmt)
>  		   && !gimple_vuse (stmt))
>  	    continue;
> diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
> index a9681ece0ae..e3e37466283 100644
> --- a/gcc/tree-sra.c
> +++ b/gcc/tree-sra.c
> @@ -1470,7 +1470,7 @@ scan_function (void)
>  	  tree t;
>  	  unsigned i;
>  
> -	  if (final_bbs && stmt_can_throw_external (stmt))
> +	  if (final_bbs && stmt_can_throw_external (cfun, stmt))
>  	    bitmap_set_bit (final_bbs, bb->index);
>  	  switch (gimple_code (stmt))
>  	    {
> diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
> index 032e79b8ba0..85a5de7ce05 100644
> --- a/gcc/tree-ssa-alias.c
> +++ b/gcc/tree-ssa-alias.c
> @@ -2396,7 +2396,7 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
>  	 ???  We only need to care about the RHS throwing.  For aggregate
>  	 assignments or similar calls and non-call exceptions the LHS
>  	 might throw as well.  */
> -      && !stmt_can_throw_internal (stmt))
> +      && !stmt_can_throw_internal (cfun, stmt))
>      {
>        tree lhs = gimple_get_lhs (stmt);
>        /* If LHS is literally a base of the access we are done.  */
> diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
> index d8a069be529..55ee30e7d13 100644
> --- a/gcc/tree-ssa-ccp.c
> +++ b/gcc/tree-ssa-ccp.c
> @@ -2931,7 +2931,7 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
>    gimple_set_location (g, gimple_location (call));
>    gimple_set_vuse (g, gimple_vuse (call));
>    gimple_set_vdef (g, gimple_vdef (call));
> -  bool throws = stmt_can_throw_internal (call);
> +  bool throws = stmt_can_throw_internal (cfun, call);
>    gimple_call_set_nothrow (as_a <gcall *> (g),
>  			   gimple_call_nothrow_p (as_a <gcall *> (call)));
>    SSA_NAME_DEF_STMT (gimple_vdef (call)) = g;
> diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
> index 91ce2aa4fc5..a8261b9a476 100644
> --- a/gcc/tree-ssa-dce.c
> +++ b/gcc/tree-ssa-dce.c
> @@ -195,7 +195,7 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
>       throw.  If a statement could throw, it can be deemed necessary.  */
>    if (cfun->can_throw_non_call_exceptions
>        && !cfun->can_delete_dead_exceptions
> -      && stmt_could_throw_p (stmt))
> +      && stmt_could_throw_p (cfun, stmt))
>      {
>        mark_stmt_necessary (stmt, true);
>        return;
> @@ -473,7 +473,7 @@ mark_aliased_reaching_defs_necessary_1 (ao_ref *ref, tree vdef, void *data)
>           ???  We only need to care about the RHS throwing.  For aggregate
>  	 assignments or similar calls and non-call exceptions the LHS
>  	 might throw as well.  */
> -      && !stmt_can_throw_internal (def_stmt))
> +      && !stmt_can_throw_internal (cfun, def_stmt))
>      {
>        tree base, lhs = gimple_get_lhs (def_stmt);
>        poly_int64 size, offset, max_size;
> diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
> index b1ee598fe5f..7449eaf86ae 100644
> --- a/gcc/tree-ssa-forwprop.c
> +++ b/gcc/tree-ssa-forwprop.c
> @@ -2343,7 +2343,7 @@ pass_forwprop::execute (function *fun)
>  		   && !gimple_has_volatile_ops (stmt)
>  		   && (TREE_CODE (gimple_assign_rhs1 (stmt))
>  		       != TARGET_MEM_REF)
> -		   && !stmt_can_throw_internal (stmt))
> +		   && !stmt_can_throw_internal (cfun, stmt))
>  	    {
>  	      /* Rewrite loads used only in real/imagpart extractions to
>  	         component-wise loads.  */
> diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
> index 9c62f20866c..3c59134d840 100644
> --- a/gcc/tree-ssa-loop-im.c
> +++ b/gcc/tree-ssa-loop-im.c
> @@ -302,7 +302,7 @@ movement_possibility (gimple *stmt)
>    if (stmt_ends_bb_p (stmt)
>        || gimple_has_volatile_ops (stmt)
>        || gimple_has_side_effects (stmt)
> -      || stmt_could_throw_p (stmt))
> +      || stmt_could_throw_p (cfun, stmt))
>      return MOVE_IMPOSSIBLE;
>  
>    if (is_gimple_call (stmt))
> diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
> index 6b445bd2214..b42f32da2b3 100644
> --- a/gcc/tree-ssa-loop-ivopts.c
> +++ b/gcc/tree-ssa-loop-ivopts.c
> @@ -1440,7 +1440,7 @@ find_givs_in_stmt_scev (struct ivopts_data *data, gimple *stmt, affine_iv *iv)
>    /* If STMT could throw, then do not consider STMT as defining a GIV.
>       While this will suppress optimizations, we can not safely delete this
>       GIV and associated statements, even if it appears it is not used.  */
> -  if (stmt_could_throw_p (stmt))
> +  if (stmt_could_throw_p (cfun, stmt))
>      return false;
>  
>    return true;
> @@ -3222,7 +3222,7 @@ add_autoinc_candidates (struct ivopts_data *data, tree base, tree step,
>       statement.  */
>    if (use_bb->loop_father != data->current_loop
>        || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb)
> -      || stmt_can_throw_internal (use->stmt)
> +      || stmt_can_throw_internal (cfun, use->stmt)
>        || !cst_and_fits_in_hwi (step))
>      return;
>  
> diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
> index e5aa5310e58..ccff56f4297 100644
> --- a/gcc/tree-ssa-math-opts.c
> +++ b/gcc/tree-ssa-math-opts.c
> @@ -951,7 +951,7 @@ pass_cse_reciprocals::execute (function *fun)
>  	      stmt = gsi_stmt (gsi);
>  	      if (flag_unsafe_math_optimizations
>  		  && is_gimple_assign (stmt)
> -		  && !stmt_can_throw_internal (stmt)
> +		  && !stmt_can_throw_internal (cfun, stmt)
>  		  && gimple_assign_rhs_code (stmt) == RDIV_EXPR)
>  		optimize_recip_sqrt (&gsi, def);
>  	    }
> @@ -2904,7 +2904,8 @@ convert_mult_to_fma_1 (tree mul_result, tree op1, tree op2)
>        else
>  	fma_stmt = gimple_build_call_internal (IFN_FMA, 3, mulop1, op2, addop);
>        gimple_set_lhs (fma_stmt, gimple_get_lhs (use_stmt));
> -      gimple_call_set_nothrow (fma_stmt, !stmt_can_throw_internal (use_stmt));
> +      gimple_call_set_nothrow (fma_stmt, !stmt_can_throw_internal (cfun,
> +								   use_stmt));
>        gsi_replace (&gsi, fma_stmt, true);
>        /* Follow all SSA edges so that we generate FMS, FNMA and FNMS
>  	 regardless of where the negation occurs.  */
> @@ -3534,7 +3535,7 @@ divmod_candidate_p (gassign *stmt)
>  static bool
>  convert_to_divmod (gassign *stmt)
>  {
> -  if (stmt_can_throw_internal (stmt)
> +  if (stmt_can_throw_internal (cfun, stmt)
>        || !divmod_candidate_p (stmt))
>      return false;
>  
> @@ -3560,7 +3561,7 @@ convert_to_divmod (gassign *stmt)
>  	  && operand_equal_p (op1, gimple_assign_rhs1 (use_stmt), 0)
>  	  && operand_equal_p (op2, gimple_assign_rhs2 (use_stmt), 0))
>  	{
> -	  if (stmt_can_throw_internal (use_stmt))
> +	  if (stmt_can_throw_internal (cfun, use_stmt))
>  	    continue;
>  
>  	  basic_block bb = gimple_bb (use_stmt);
> @@ -3598,7 +3599,7 @@ convert_to_divmod (gassign *stmt)
>  	  && operand_equal_p (top_op2, gimple_assign_rhs2 (use_stmt), 0))
>  	{
>  	  if (use_stmt == top_stmt
> -	      || stmt_can_throw_internal (use_stmt)
> +	      || stmt_can_throw_internal (cfun, use_stmt)
>  	      || !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), top_bb))
>  	    continue;
>  
> diff --git a/gcc/tree-ssa-phiprop.c b/gcc/tree-ssa-phiprop.c
> index 03dbb390bf8..bb18f3e9b49 100644
> --- a/gcc/tree-ssa-phiprop.c
> +++ b/gcc/tree-ssa-phiprop.c
> @@ -339,7 +339,7 @@ propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
>  		|| types_compatible_p
>  		     (TREE_TYPE (gimple_assign_lhs (use_stmt)), type))
>  	    /* We cannot replace a load that may throw or is volatile.  */
> -	    && !stmt_can_throw_internal (use_stmt)))
> +	    && !stmt_can_throw_internal (cfun, use_stmt)))
>  	continue;
>  
>        /* Check if we can move the loads.  The def stmt of the virtual use
> diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
> index d1b0cc0c26f..20d3c7807a1 100644
> --- a/gcc/tree-ssa-pre.c
> +++ b/gcc/tree-ssa-pre.c
> @@ -3827,7 +3827,7 @@ compute_avail (void)
>  	    BB_LIVE_VOP_ON_EXIT (block) = gimple_vdef (stmt);
>  
>  	  if (gimple_has_side_effects (stmt)
> -	      || stmt_could_throw_p (stmt)
> +	      || stmt_could_throw_p (cfun, stmt)
>  	      || is_gimple_debug (stmt))
>  	    continue;
>  
> diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
> index b1bfdd5c016..c635e3069f4 100644
> --- a/gcc/tree-ssa-propagate.c
> +++ b/gcc/tree-ssa-propagate.c
> @@ -1038,7 +1038,7 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
>  	  if (sprime
>  	      && sprime != lhs
>  	      && may_propagate_copy (lhs, sprime)
> -	      && !stmt_could_throw_p (stmt)
> +	      && !stmt_could_throw_p (cfun, stmt)
>  	      && !gimple_has_side_effects (stmt)
>  	      /* We have to leave ASSERT_EXPRs around for jump-threading.  */
>  	      && (!is_gimple_assign (stmt)
> diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
> index 6b0bf5c0354..971d926e789 100644
> --- a/gcc/tree-ssa-reassoc.c
> +++ b/gcc/tree-ssa-reassoc.c
> @@ -3702,7 +3702,7 @@ suitable_cond_bb (basic_block bb, basic_block test_bb, basic_block *other_bb,
>        || (gimple_code (stmt) != GIMPLE_COND
>  	  && (backward || !final_range_test_p (stmt)))
>        || gimple_visited_p (stmt)
> -      || stmt_could_throw_p (stmt)
> +      || stmt_could_throw_p (cfun, stmt)
>        || *other_bb == bb)
>      return false;
>    is_cond = gimple_code (stmt) == GIMPLE_COND;
> @@ -3958,7 +3958,7 @@ maybe_optimize_range_tests (gimple *stmt)
>    else
>      return cfg_cleanup_needed;
>  
> -  if (stmt_could_throw_p (stmt))
> +  if (stmt_could_throw_p (cfun, stmt))
>      return cfg_cleanup_needed;
>  
>    /* As relative ordering of post-dominator sons isn't fixed,
> @@ -5109,14 +5109,14 @@ linearize_expr_tree (vec<operand_entry *> *ops, gimple *stmt,
>      {
>        binlhsdef = SSA_NAME_DEF_STMT (binlhs);
>        binlhsisreassoc = (is_reassociable_op (binlhsdef, rhscode, loop)
> -			 && !stmt_could_throw_p (binlhsdef));
> +			 && !stmt_could_throw_p (cfun, binlhsdef));
>      }
>  
>    if (TREE_CODE (binrhs) == SSA_NAME)
>      {
>        binrhsdef = SSA_NAME_DEF_STMT (binrhs);
>        binrhsisreassoc = (is_reassociable_op (binrhsdef, rhscode, loop)
> -			 && !stmt_could_throw_p (binrhsdef));
> +			 && !stmt_could_throw_p (cfun, binrhsdef));
>      }
>  
>    /* If the LHS is not reassociable, but the RHS is, we need to swap
> @@ -5851,7 +5851,7 @@ reassociate_bb (basic_block bb)
>        stmt = gsi_stmt (gsi);
>  
>        if (is_gimple_assign (stmt)
> -	  && !stmt_could_throw_p (stmt))
> +	  && !stmt_could_throw_p (cfun, stmt))
>  	{
>  	  tree lhs, rhs1, rhs2;
>  	  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
> diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
> index 5a05dfb5640..e61f0ba7b8c 100644
> --- a/gcc/tree-ssa-sccvn.c
> +++ b/gcc/tree-ssa-sccvn.c
> @@ -1210,7 +1210,7 @@ copy_reference_ops_from_call (gcall *call,
>    temp.opcode = CALL_EXPR;
>    temp.op0 = gimple_call_fn (call);
>    temp.op1 = gimple_call_chain (call);
> -  if (stmt_could_throw_p (call) && (lr = lookup_stmt_eh_lp (call)) > 0)
> +  if (stmt_could_throw_p (cfun, call) && (lr = lookup_stmt_eh_lp (call)) > 0)
>      temp.op2 = size_int (lr);
>    temp.off = -1;
>    result->safe_push (temp);
> diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c
> index 9e751a27152..d1a73a5d64c 100644
> --- a/gcc/tree-ssa-scopedtables.c
> +++ b/gcc/tree-ssa-scopedtables.c
> @@ -666,7 +666,7 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
>                                   expr1->ops.call.args[i], 0))
>              return false;
>  
> -	if (stmt_could_throw_p (expr0->ops.call.fn_from))
> +	if (stmt_could_throw_p (cfun, expr0->ops.call.fn_from))
>  	  {
>  	    int lp0 = lookup_stmt_eh_lp (expr0->ops.call.fn_from);
>  	    int lp1 = lookup_stmt_eh_lp (expr1->ops.call.fn_from);
> diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
> index 3fa5ef56f38..fd8c2750116 100644
> --- a/gcc/tree-ssa-strlen.c
> +++ b/gcc/tree-ssa-strlen.c
> @@ -1064,7 +1064,7 @@ adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
>  
>        if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
>  	return;
> -      if (stmt_could_throw_p (last.stmt))
> +      if (stmt_could_throw_p (cfun, last.stmt))
>  	return;
>        gsi = gsi_for_stmt (last.stmt);
>        unlink_stmt_vdef (last.stmt);
> @@ -3253,7 +3253,7 @@ handle_char_store (gimple_stmt_iterator *gsi)
>  	{
>  	  /* When overwriting a '\0' with a '\0', the store can be removed
>  	     if we know it has been stored in the current function.  */
> -	  if (!stmt_could_throw_p (stmt) && si->writable)
> +	  if (!stmt_could_throw_p (cfun, stmt) && si->writable)
>  	    {
>  	      unlink_stmt_vdef (stmt);
>  	      release_defs (stmt);
> diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
> index c4805e72447..4b3711442e6 100644
> --- a/gcc/tree-vect-data-refs.c
> +++ b/gcc/tree-vect-data-refs.c
> @@ -3844,7 +3844,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
>      return opt_result::failure_at (stmt, "not vectorized: volatile type: %G",
>  				   stmt);
>  
> -  if (stmt_can_throw_internal (stmt))
> +  if (stmt_can_throw_internal (cfun, stmt))
>      return opt_result::failure_at (stmt,
>  				   "not vectorized:"
>  				   " statement can throw an exception: %G",
> diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
> index 7956c1326d3..5548d47b87f 100644
> --- a/gcc/tree-vect-patterns.c
> +++ b/gcc/tree-vect-patterns.c
> @@ -3235,7 +3235,7 @@ check_bool_pattern (tree var, vec_info *vinfo, hash_set<gimple *> &stmts)
>  
>  	  /* If the comparison can throw, then is_gimple_condexpr will be
>  	     false and we can't make a COND_EXPR/VEC_COND_EXPR out of it.  */
> -	  if (stmt_could_throw_p (def_stmt))
> +	  if (stmt_could_throw_p (cfun, def_stmt))
>  	    return false;
>  
>  	  comp_vectype = get_vectype_for_scalar_type (TREE_TYPE (rhs1));
> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
> index 8108d52a3cb..8995da80b1e 100644
> --- a/gcc/tree-vect-stmts.c
> +++ b/gcc/tree-vect-stmts.c
> @@ -1711,7 +1711,7 @@ vect_finish_stmt_generation_1 (stmt_vec_info stmt_info, gimple *vec_stmt)
>       e.g. be in a must-not-throw region.  Ensure newly created stmts
>       that could throw are part of the same region.  */
>    int lp_nr = lookup_stmt_eh_lp (stmt_info->stmt);
> -  if (lp_nr != 0 && stmt_could_throw_p (vec_stmt))
> +  if (lp_nr != 0 && stmt_could_throw_p (cfun, vec_stmt))
>      add_stmt_to_eh_lp (vec_stmt, lp_nr);
>  
>    return vec_stmt_info;
> @@ -3116,7 +3116,7 @@ vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
>        || TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
>      return false;
>  
> -  gcc_checking_assert (!stmt_can_throw_internal (stmt));
> +  gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
>  
>    vectype_out = STMT_VINFO_VECTYPE (stmt_info);
>  
> @@ -3751,7 +3751,7 @@ vectorizable_simd_clone_call (stmt_vec_info stmt_info,
>        && TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
>      return false;
>  
> -  gcc_checking_assert (!stmt_can_throw_internal (stmt));
> +  gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
>  
>    vectype = STMT_VINFO_VECTYPE (stmt_info);
>  
> diff --git a/gcc/value-prof.c b/gcc/value-prof.c
> index 60b982793d1..f3be9ff8747 100644
> --- a/gcc/value-prof.c
> +++ b/gcc/value-prof.c
> @@ -1392,7 +1392,7 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
>  
>    /* Build an EH edge for the direct call if necessary.  */
>    lp_nr = lookup_stmt_eh_lp (icall_stmt);
> -  if (lp_nr > 0 && stmt_could_throw_p (dcall_stmt))
> +  if (lp_nr > 0 && stmt_could_throw_p (cfun, dcall_stmt))
>      {
>        add_stmt_to_eh_lp (dcall_stmt, lp_nr);
>      }
> @@ -1410,7 +1410,7 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
>  		     PHI_ARG_DEF_FROM_EDGE (phi, e_eh));
>  	  }
>         }
> -  if (!stmt_could_throw_p (dcall_stmt))
> +  if (!stmt_could_throw_p (cfun, dcall_stmt))
>      gimple_purge_dead_eh_edges (dcall_bb);
>    return dcall_stmt;
>  }
> @@ -1634,8 +1634,8 @@ gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, profile_probabi
>      }
>  
>    /* Because these are all string op builtins, they're all nothrow.  */
> -  gcc_assert (!stmt_could_throw_p (vcall_stmt));
> -  gcc_assert (!stmt_could_throw_p (icall_stmt));
> +  gcc_assert (!stmt_could_throw_p (cfun, vcall_stmt));
> +  gcc_assert (!stmt_could_throw_p (cfun, icall_stmt));
>  }
>  
>  /* Find values inside STMT for that we want to measure histograms for
>
diff mbox series

Patch

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 8a03f3d6828..48bab9f2749 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -815,9 +815,8 @@  cgraph_edge::set_call_stmt (gcall *new_stmt, bool update_speculative)
       e = make_direct (new_callee);
     }
 
-  push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
-  e->can_throw_external = stmt_can_throw_external (new_stmt);
-  pop_cfun ();
+  function *fun = DECL_STRUCT_FUNCTION (e->caller->decl);
+  e->can_throw_external = stmt_can_throw_external (fun, new_stmt);
   if (e->caller->call_site_hash)
     cgraph_add_edge_to_call_site_hash (e);
 }
@@ -870,10 +869,9 @@  symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
   edge->count = count;
 
   edge->call_stmt = call_stmt;
-  push_cfun (DECL_STRUCT_FUNCTION (caller->decl));
   edge->can_throw_external
-    = call_stmt ? stmt_can_throw_external (call_stmt) : false;
-  pop_cfun ();
+    = call_stmt ? stmt_can_throw_external (DECL_STRUCT_FUNCTION (caller->decl),
+					   call_stmt) : false;
   if (call_stmt
       && callee && callee->decl
       && !gimple_check_call_matching_types (call_stmt, callee->decl,
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index fe6bc08bdd9..e862b1a1d4c 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -4023,7 +4023,7 @@  fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *gsi)
   gimple_set_vuse (g, gimple_vuse (stmt));
   SSA_NAME_DEF_STMT (gimple_vdef (g)) = g;
   tree oldlhs = gimple_call_lhs (stmt);
-  if (stmt_can_throw_internal (stmt))
+  if (stmt_can_throw_internal (cfun, stmt))
     {
       throws = true;
       e = find_fallthru_edge (gsi_bb (*gsi)->succs);
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index 50e8adc1aad..7d952765c5a 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -164,7 +164,7 @@  evrp_dom_walker::before_dom_children (basic_block bb)
 	      if ((vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE)
 		  && (val = value_range_constant_singleton (vr))
 		  && may_propagate_copy (output, val)
-		  && !stmt_could_throw_p (stmt)
+		  && !stmt_could_throw_p (cfun, stmt)
 		  && !gimple_has_side_effects (stmt))
 		{
 		  stmts_to_remove.safe_push (stmt);
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 85dd5bccead..e1ddcb5e558 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -4256,7 +4256,7 @@  handled_load (gimple *stmt, store_operand_info *op,
     }
   if (gimple_vuse (stmt)
       && gimple_assign_load_p (stmt)
-      && !stmt_can_throw_internal (stmt)
+      && !stmt_can_throw_internal (cfun, stmt)
       && !gimple_has_volatile_ops (stmt))
     {
       tree mem = gimple_assign_rhs1 (stmt);
@@ -4551,7 +4551,7 @@  pass_store_merging::execute (function *fun)
 	    }
 
 	  if (gimple_assign_single_p (stmt) && gimple_vdef (stmt)
-	      && !stmt_can_throw_internal (stmt)
+	      && !stmt_can_throw_internal (cfun, stmt)
 	      && lhs_valid_for_store_merging_p (gimple_assign_lhs (stmt)))
 	    process_store (stmt);
 	  else
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index ea81adca7ea..7ed6ae7f88a 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -1775,7 +1775,7 @@  find_candidates_dom_walker::before_dom_children (basic_block bb)
     {
       gimple *gs = gsi_stmt (gsi);
 
-      if (stmt_could_throw_p (gs))
+      if (stmt_could_throw_p (cfun, gs))
 	continue;
 
       if (gimple_vuse (gs) && gimple_assign_single_p (gs))
diff --git a/gcc/gimplify-me.c b/gcc/gimplify-me.c
index 137a5662ccf..269fe6b3bae 100644
--- a/gcc/gimplify-me.c
+++ b/gcc/gimplify-me.c
@@ -273,7 +273,7 @@  gimple_regimplify_operands (gimple *stmt, gimple_stmt_iterator *gsi_p)
 			  || !(i & (ECF_CONST | ECF_PURE)))
 			need_temp = true;
 		    }
-		  if (stmt_can_throw_internal (stmt))
+		  if (stmt_can_throw_internal (cfun, stmt))
 		    need_temp = true;
 		}
 	    }
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 66c81be23ec..1ca1d60517e 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -555,9 +555,9 @@  check_call (funct_state local, gcall *call, bool ipa)
 {
   int flags = gimple_call_flags (call);
   tree callee_t = gimple_call_fndecl (call);
-  bool possibly_throws = stmt_could_throw_p (call);
+  bool possibly_throws = stmt_could_throw_p (cfun, call);
   bool possibly_throws_externally = (possibly_throws
-  				     && stmt_can_throw_external (call));
+  				     && stmt_can_throw_external (cfun, call));
 
   if (possibly_throws)
     {
@@ -770,7 +770,7 @@  check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
 			    ipa ? check_ipa_store :  check_store);
 
   if (gimple_code (stmt) != GIMPLE_CALL
-      && stmt_could_throw_p (stmt))
+      && stmt_could_throw_p (cfun, stmt))
     {
       if (cfun->can_throw_non_call_exceptions)
 	{
@@ -778,7 +778,7 @@  check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
 	    fprintf (dump_file, "    can throw; looping\n");
 	  local->looping = true;
 	}
-      if (stmt_can_throw_external (stmt))
+      if (stmt_can_throw_external (cfun, stmt))
 	{
 	  if (dump_file)
 	    fprintf (dump_file, "    can throw externally\n");
@@ -2307,7 +2307,7 @@  pass_nothrow::execute (function *)
       for (gimple_stmt_iterator gsi = gsi_start_bb (this_block);
 	   !gsi_end_p (gsi);
 	   gsi_next (&gsi))
-        if (stmt_can_throw_external (gsi_stmt (gsi)))
+        if (stmt_can_throw_external (cfun, gsi_stmt (gsi)))
 	  {
 	    if (is_gimple_call (gsi_stmt (gsi)))
 	      {
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 1d4eb806202..7e4bcec4030 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -2582,7 +2582,7 @@  expand_call_tm (struct tm_region *region,
       gassign *assign_stmt;
 
       /* Remember if the call was going to throw.  */
-      if (stmt_can_throw_internal (stmt))
+      if (stmt_can_throw_internal (cfun, stmt))
 	{
 	  edge_iterator ei;
 	  edge e;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 87979bc4d75..d30e4aca773 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2720,7 +2720,7 @@  is_ctrl_altering_stmt (gimple *t)
     }
 
   /* If a statement can throw, it alters control flow.  */
-  return stmt_can_throw_internal (t);
+  return stmt_can_throw_internal (cfun, t);
 }
 
 
@@ -5387,7 +5387,7 @@  verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
 	    visited_throwing_stmts.add (stmt);
 	  if (lp_nr > 0)
 	    {
-	      if (!stmt_could_throw_p (stmt))
+	      if (!stmt_could_throw_p (cfun, stmt))
 		{
 		  if (verify_nothrow)
 		    {
@@ -8283,7 +8283,7 @@  stmt_can_terminate_bb_p (gimple *t)
 
   /* Eh exception not handled internally terminates execution of the whole
      function.  */
-  if (stmt_can_throw_external (t))
+  if (stmt_can_throw_external (cfun, t))
     return true;
 
   /* NORETURN and LONGJMP calls already have an edge to exit.
@@ -8599,7 +8599,7 @@  gimple_purge_dead_eh_edges (basic_block bb)
   edge_iterator ei;
   gimple *stmt = last_stmt (bb);
 
-  if (stmt && stmt_can_throw_internal (stmt))
+  if (stmt && stmt_can_throw_internal (cfun, stmt))
     return false;
 
   for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 93f274cd213..49088081bb0 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -1010,13 +1010,13 @@  expand_complex_libcall (gimple_stmt_iterator *gsi, tree type, tree ar, tree ai,
   if (inplace_p)
     {
       gimple *old_stmt = gsi_stmt (*gsi);
-      gimple_call_set_nothrow (stmt, !stmt_could_throw_p (old_stmt));
+      gimple_call_set_nothrow (stmt, !stmt_could_throw_p (cfun, old_stmt));
       lhs = gimple_assign_lhs (old_stmt);
       gimple_call_set_lhs (stmt, lhs);
       gsi_replace (gsi, stmt, true);
 
       type = TREE_TYPE (type);
-      if (stmt_can_throw_internal (stmt))
+      if (stmt_can_throw_internal (cfun, stmt))
 	{
 	  edge_iterator ei;
 	  edge e;
@@ -1134,7 +1134,7 @@  expand_complex_multiplication (gimple_stmt_iterator *gsi, tree type,
 	  /* If optimizing for size or not at all just do a libcall.
 	     Same if there are exception-handling edges or signaling NaNs.  */
 	  if (optimize == 0 || optimize_bb_for_size_p (gsi_bb (*gsi))
-	     || stmt_can_throw_internal (gsi_stmt (*gsi))
+	     || stmt_can_throw_internal (cfun, gsi_stmt (*gsi))
 	     || flag_signaling_nans)
 	    {
 	      expand_complex_libcall (gsi, type, ar, ai, br, bi,
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index fb931aa4389..1c7d9dc1d59 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2033,7 +2033,7 @@  lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
 	 available on the EH edge.  Only do so for statements that
 	 potentially fall through (no noreturn calls e.g.), otherwise
 	 this new assignment might create fake fallthru regions.  */
-      if (stmt_could_throw_p (stmt)
+      if (stmt_could_throw_p (cfun, stmt)
 	  && gimple_has_lhs (stmt)
 	  && gimple_stmt_may_fallthru (stmt)
 	  && !tree_could_throw_p (gimple_get_lhs (stmt))
@@ -2051,7 +2051,7 @@  lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
 	  gsi_insert_after (gsi, s, GSI_SAME_STMT);
 	}
       /* Look for things that can throw exceptions, and record them.  */
-      if (state->cur_region && stmt_could_throw_p (stmt))
+      if (state->cur_region && stmt_could_throw_p (cfun, stmt))
 	{
 	  record_stmt_eh_region (state->cur_region, stmt);
 	  note_eh_region_may_contain_throw (state->cur_region);
@@ -2866,10 +2866,10 @@  stmt_could_throw_1_p (gassign *stmt)
 }
 
 
-/* Return true if statement STMT could throw an exception.  */
+/* Return true if statement STMT within FUN could throw an exception.  */
 
 bool
-stmt_could_throw_p (gimple *stmt)
+stmt_could_throw_p (function *fun, gimple *stmt)
 {
   if (!flag_exceptions)
     return false;
@@ -2886,7 +2886,7 @@  stmt_could_throw_p (gimple *stmt)
 
     case GIMPLE_COND:
       {
-	if (!cfun->can_throw_non_call_exceptions)
+	if (fun && !fun->can_throw_non_call_exceptions)
 	  return false;
 	gcond *cond = as_a <gcond *> (stmt);
 	tree lhs = gimple_cond_lhs (cond);
@@ -2896,13 +2896,13 @@  stmt_could_throw_p (gimple *stmt)
       }
 
     case GIMPLE_ASSIGN:
-      if (!cfun->can_throw_non_call_exceptions
+      if ((fun && !fun->can_throw_non_call_exceptions)
 	  || gimple_clobber_p (stmt))
         return false;
       return stmt_could_throw_1_p (as_a <gassign *> (stmt));
 
     case GIMPLE_ASM:
-      if (!cfun->can_throw_non_call_exceptions)
+      if (fun && !fun->can_throw_non_call_exceptions)
         return false;
       return gimple_asm_volatile_p (as_a <gasm *> (stmt));
 
@@ -2936,33 +2936,37 @@  tree_could_throw_p (tree t)
   return false;
 }
 
-/* Return true if STMT can throw an exception that is not caught within
-   the current function (CFUN).  */
+/* Return true if STMT can throw an exception that is not caught within its
+   function FUN.  FUN can be NULL but the function is extra conservative
+   then.  */
 
 bool
-stmt_can_throw_external (gimple *stmt)
+stmt_can_throw_external (function *fun, gimple *stmt)
 {
   int lp_nr;
 
-  if (!stmt_could_throw_p (stmt))
+  if (!stmt_could_throw_p (fun, stmt))
     return false;
+  if (!fun)
+    return true;
 
-  lp_nr = lookup_stmt_eh_lp (stmt);
+  lp_nr = lookup_stmt_eh_lp_fn (fun, stmt);
   return lp_nr == 0;
 }
 
-/* Return true if STMT can throw an exception that is caught within
-   the current function (CFUN).  */
+/* Return true if STMT can throw an exception that is caught within its
+   function FUN.  */
 
 bool
-stmt_can_throw_internal (gimple *stmt)
+stmt_can_throw_internal (function *fun, gimple *stmt)
 {
   int lp_nr;
 
-  if (!stmt_could_throw_p (stmt))
+  gcc_checking_assert (fun);
+  if (!stmt_could_throw_p (fun, stmt))
     return false;
 
-  lp_nr = lookup_stmt_eh_lp (stmt);
+  lp_nr = lookup_stmt_eh_lp_fn (fun, stmt);
   return lp_nr > 0;
 }
 
@@ -2973,7 +2977,7 @@  stmt_can_throw_internal (gimple *stmt)
 bool
 maybe_clean_eh_stmt_fn (struct function *ifun, gimple *stmt)
 {
-  if (stmt_could_throw_p (stmt))
+  if (stmt_could_throw_p (ifun, stmt))
     return false;
   return remove_stmt_from_eh_lp_fn (ifun, stmt);
 }
@@ -2998,7 +3002,7 @@  maybe_clean_or_replace_eh_stmt (gimple *old_stmt, gimple *new_stmt)
 
   if (lp_nr != 0)
     {
-      bool new_stmt_could_throw = stmt_could_throw_p (new_stmt);
+      bool new_stmt_could_throw = stmt_could_throw_p (cfun, new_stmt);
 
       if (new_stmt == old_stmt && new_stmt_could_throw)
 	return false;
@@ -3028,7 +3032,7 @@  maybe_duplicate_eh_stmt_fn (struct function *new_fun, gimple *new_stmt,
 {
   int old_lp_nr, new_lp_nr;
 
-  if (!stmt_could_throw_p (new_stmt))
+  if (!stmt_could_throw_p (new_fun, new_stmt))
     return false;
 
   old_lp_nr = lookup_stmt_eh_lp_fn (old_fun, old_stmt);
@@ -3067,7 +3071,7 @@  maybe_duplicate_eh_stmt (gimple *new_stmt, gimple *old_stmt)
 {
   int lp_nr;
 
-  if (!stmt_could_throw_p (new_stmt))
+  if (!stmt_could_throw_p (cfun, new_stmt))
     return false;
 
   lp_nr = lookup_stmt_eh_lp (old_stmt);
@@ -3862,7 +3866,7 @@  pass_lower_eh_dispatch::execute (function *fun)
 	}
       else if (gimple_code (last) == GIMPLE_RESX)
 	{
-	  if (stmt_can_throw_external (last))
+	  if (stmt_can_throw_external (cfun, last))
 	    optimize_clobbers (bb);
 	  else
 	    flags |= sink_clobbers (bb);
@@ -4502,7 +4506,7 @@  cleanup_empty_eh (eh_landing_pad lp)
   resx = gsi_stmt (gsi);
   if (resx && is_gimple_resx (resx))
     {
-      if (stmt_can_throw_external (resx))
+      if (stmt_can_throw_external (cfun, resx))
 	optimize_clobbers (bb);
       else if (sink_clobbers (bb))
 	ret = true;
@@ -4783,7 +4787,7 @@  verify_eh_edges (gimple *stmt)
       return false;
     }
 
-  if (!stmt_could_throw_p (stmt))
+  if (!stmt_could_throw_p (cfun, stmt))
     {
       error ("BB %i last statement has incorrectly set lp", bb->index);
       return true;
diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h
index 11e096c9e5f..2bd6a856bd9 100644
--- a/gcc/tree-eh.h
+++ b/gcc/tree-eh.h
@@ -38,10 +38,10 @@  extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
 extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
 extern bool tree_could_trap_p (tree);
 extern tree rewrite_to_non_trapping_overflow (tree);
-extern bool stmt_could_throw_p (gimple *);
+extern bool stmt_could_throw_p (function *, gimple *);
 extern bool tree_could_throw_p (tree);
-extern bool stmt_can_throw_external (gimple *);
-extern bool stmt_can_throw_internal (gimple *);
+extern bool stmt_can_throw_external (function *, gimple *);
+extern bool stmt_can_throw_internal (function *, gimple *);
 extern bool maybe_clean_eh_stmt_fn (struct function *, gimple *);
 extern bool maybe_clean_eh_stmt (gimple *);
 extern bool maybe_clean_or_replace_eh_stmt (gimple *, gimple *);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 913425394e0..297fcd70c82 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2246,7 +2246,7 @@  copy_edges_for_bb (basic_block bb, profile_count num, profile_count den,
          propagation can change an INDIRECT_REF which throws
          into a COMPONENT_REF which doesn't.  If the copy
          can throw, the original could also throw.  */
-      can_throw = stmt_can_throw_internal (copy_stmt);
+      can_throw = stmt_can_throw_internal (cfun, copy_stmt);
       nonlocal_goto
 	= (stmt_can_make_abnormal_goto (copy_stmt)
 	   && !computed_goto_p (copy_stmt));
@@ -2514,7 +2514,7 @@  maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
 
   if (gsi_end_p (si)
       || gsi_one_before_end_p (si)
-      || !(stmt_can_throw_internal (gsi_stmt (si))
+      || !(stmt_can_throw_internal (cfun, gsi_stmt (si))
 	   || stmt_can_make_abnormal_goto (gsi_stmt (si))))
     return;
 
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 3f880ef7382..fca15e5f898 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -65,7 +65,7 @@  ssa_is_replaceable_p (gimple *stmt)
     return false;
 
   /* If the statement may throw an exception, it cannot be replaced.  */
-  if (stmt_could_throw_p (stmt))
+  if (stmt_could_throw_p (cfun, stmt))
     return false;
 
   /* Punt if there is more than 1 def.  */
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index e89c8875147..5935cf40927 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -3076,7 +3076,7 @@  oacc_entry_exit_ok_1 (bitmap in_loop_bbs, vec<basic_block> region_bbs,
 	    continue;
 	  else if (!gimple_has_side_effects (stmt)
 		   && !gimple_could_trap_p (stmt)
-		   && !stmt_could_throw_p (stmt)
+		   && !stmt_could_throw_p (cfun, stmt)
 		   && !gimple_vdef (stmt)
 		   && !gimple_vuse (stmt))
 	    continue;
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index a9681ece0ae..e3e37466283 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1470,7 +1470,7 @@  scan_function (void)
 	  tree t;
 	  unsigned i;
 
-	  if (final_bbs && stmt_can_throw_external (stmt))
+	  if (final_bbs && stmt_can_throw_external (cfun, stmt))
 	    bitmap_set_bit (final_bbs, bb->index);
 	  switch (gimple_code (stmt))
 	    {
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 032e79b8ba0..85a5de7ce05 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2396,7 +2396,7 @@  stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
 	 ???  We only need to care about the RHS throwing.  For aggregate
 	 assignments or similar calls and non-call exceptions the LHS
 	 might throw as well.  */
-      && !stmt_can_throw_internal (stmt))
+      && !stmt_can_throw_internal (cfun, stmt))
     {
       tree lhs = gimple_get_lhs (stmt);
       /* If LHS is literally a base of the access we are done.  */
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index d8a069be529..55ee30e7d13 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2931,7 +2931,7 @@  optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
   gimple_set_location (g, gimple_location (call));
   gimple_set_vuse (g, gimple_vuse (call));
   gimple_set_vdef (g, gimple_vdef (call));
-  bool throws = stmt_can_throw_internal (call);
+  bool throws = stmt_can_throw_internal (cfun, call);
   gimple_call_set_nothrow (as_a <gcall *> (g),
 			   gimple_call_nothrow_p (as_a <gcall *> (call)));
   SSA_NAME_DEF_STMT (gimple_vdef (call)) = g;
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 91ce2aa4fc5..a8261b9a476 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -195,7 +195,7 @@  mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
      throw.  If a statement could throw, it can be deemed necessary.  */
   if (cfun->can_throw_non_call_exceptions
       && !cfun->can_delete_dead_exceptions
-      && stmt_could_throw_p (stmt))
+      && stmt_could_throw_p (cfun, stmt))
     {
       mark_stmt_necessary (stmt, true);
       return;
@@ -473,7 +473,7 @@  mark_aliased_reaching_defs_necessary_1 (ao_ref *ref, tree vdef, void *data)
          ???  We only need to care about the RHS throwing.  For aggregate
 	 assignments or similar calls and non-call exceptions the LHS
 	 might throw as well.  */
-      && !stmt_can_throw_internal (def_stmt))
+      && !stmt_can_throw_internal (cfun, def_stmt))
     {
       tree base, lhs = gimple_get_lhs (def_stmt);
       poly_int64 size, offset, max_size;
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index b1ee598fe5f..7449eaf86ae 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2343,7 +2343,7 @@  pass_forwprop::execute (function *fun)
 		   && !gimple_has_volatile_ops (stmt)
 		   && (TREE_CODE (gimple_assign_rhs1 (stmt))
 		       != TARGET_MEM_REF)
-		   && !stmt_can_throw_internal (stmt))
+		   && !stmt_can_throw_internal (cfun, stmt))
 	    {
 	      /* Rewrite loads used only in real/imagpart extractions to
 	         component-wise loads.  */
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 9c62f20866c..3c59134d840 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -302,7 +302,7 @@  movement_possibility (gimple *stmt)
   if (stmt_ends_bb_p (stmt)
       || gimple_has_volatile_ops (stmt)
       || gimple_has_side_effects (stmt)
-      || stmt_could_throw_p (stmt))
+      || stmt_could_throw_p (cfun, stmt))
     return MOVE_IMPOSSIBLE;
 
   if (is_gimple_call (stmt))
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 6b445bd2214..b42f32da2b3 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -1440,7 +1440,7 @@  find_givs_in_stmt_scev (struct ivopts_data *data, gimple *stmt, affine_iv *iv)
   /* If STMT could throw, then do not consider STMT as defining a GIV.
      While this will suppress optimizations, we can not safely delete this
      GIV and associated statements, even if it appears it is not used.  */
-  if (stmt_could_throw_p (stmt))
+  if (stmt_could_throw_p (cfun, stmt))
     return false;
 
   return true;
@@ -3222,7 +3222,7 @@  add_autoinc_candidates (struct ivopts_data *data, tree base, tree step,
      statement.  */
   if (use_bb->loop_father != data->current_loop
       || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb)
-      || stmt_can_throw_internal (use->stmt)
+      || stmt_can_throw_internal (cfun, use->stmt)
       || !cst_and_fits_in_hwi (step))
     return;
 
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index e5aa5310e58..ccff56f4297 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -951,7 +951,7 @@  pass_cse_reciprocals::execute (function *fun)
 	      stmt = gsi_stmt (gsi);
 	      if (flag_unsafe_math_optimizations
 		  && is_gimple_assign (stmt)
-		  && !stmt_can_throw_internal (stmt)
+		  && !stmt_can_throw_internal (cfun, stmt)
 		  && gimple_assign_rhs_code (stmt) == RDIV_EXPR)
 		optimize_recip_sqrt (&gsi, def);
 	    }
@@ -2904,7 +2904,8 @@  convert_mult_to_fma_1 (tree mul_result, tree op1, tree op2)
       else
 	fma_stmt = gimple_build_call_internal (IFN_FMA, 3, mulop1, op2, addop);
       gimple_set_lhs (fma_stmt, gimple_get_lhs (use_stmt));
-      gimple_call_set_nothrow (fma_stmt, !stmt_can_throw_internal (use_stmt));
+      gimple_call_set_nothrow (fma_stmt, !stmt_can_throw_internal (cfun,
+								   use_stmt));
       gsi_replace (&gsi, fma_stmt, true);
       /* Follow all SSA edges so that we generate FMS, FNMA and FNMS
 	 regardless of where the negation occurs.  */
@@ -3534,7 +3535,7 @@  divmod_candidate_p (gassign *stmt)
 static bool
 convert_to_divmod (gassign *stmt)
 {
-  if (stmt_can_throw_internal (stmt)
+  if (stmt_can_throw_internal (cfun, stmt)
       || !divmod_candidate_p (stmt))
     return false;
 
@@ -3560,7 +3561,7 @@  convert_to_divmod (gassign *stmt)
 	  && operand_equal_p (op1, gimple_assign_rhs1 (use_stmt), 0)
 	  && operand_equal_p (op2, gimple_assign_rhs2 (use_stmt), 0))
 	{
-	  if (stmt_can_throw_internal (use_stmt))
+	  if (stmt_can_throw_internal (cfun, use_stmt))
 	    continue;
 
 	  basic_block bb = gimple_bb (use_stmt);
@@ -3598,7 +3599,7 @@  convert_to_divmod (gassign *stmt)
 	  && operand_equal_p (top_op2, gimple_assign_rhs2 (use_stmt), 0))
 	{
 	  if (use_stmt == top_stmt
-	      || stmt_can_throw_internal (use_stmt)
+	      || stmt_can_throw_internal (cfun, use_stmt)
 	      || !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), top_bb))
 	    continue;
 
diff --git a/gcc/tree-ssa-phiprop.c b/gcc/tree-ssa-phiprop.c
index 03dbb390bf8..bb18f3e9b49 100644
--- a/gcc/tree-ssa-phiprop.c
+++ b/gcc/tree-ssa-phiprop.c
@@ -339,7 +339,7 @@  propagate_with_phi (basic_block bb, gphi *phi, struct phiprop_d *phivn,
 		|| types_compatible_p
 		     (TREE_TYPE (gimple_assign_lhs (use_stmt)), type))
 	    /* We cannot replace a load that may throw or is volatile.  */
-	    && !stmt_can_throw_internal (use_stmt)))
+	    && !stmt_can_throw_internal (cfun, use_stmt)))
 	continue;
 
       /* Check if we can move the loads.  The def stmt of the virtual use
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index d1b0cc0c26f..20d3c7807a1 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3827,7 +3827,7 @@  compute_avail (void)
 	    BB_LIVE_VOP_ON_EXIT (block) = gimple_vdef (stmt);
 
 	  if (gimple_has_side_effects (stmt)
-	      || stmt_could_throw_p (stmt)
+	      || stmt_could_throw_p (cfun, stmt)
 	      || is_gimple_debug (stmt))
 	    continue;
 
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index b1bfdd5c016..c635e3069f4 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1038,7 +1038,7 @@  substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
 	  if (sprime
 	      && sprime != lhs
 	      && may_propagate_copy (lhs, sprime)
-	      && !stmt_could_throw_p (stmt)
+	      && !stmt_could_throw_p (cfun, stmt)
 	      && !gimple_has_side_effects (stmt)
 	      /* We have to leave ASSERT_EXPRs around for jump-threading.  */
 	      && (!is_gimple_assign (stmt)
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 6b0bf5c0354..971d926e789 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -3702,7 +3702,7 @@  suitable_cond_bb (basic_block bb, basic_block test_bb, basic_block *other_bb,
       || (gimple_code (stmt) != GIMPLE_COND
 	  && (backward || !final_range_test_p (stmt)))
       || gimple_visited_p (stmt)
-      || stmt_could_throw_p (stmt)
+      || stmt_could_throw_p (cfun, stmt)
       || *other_bb == bb)
     return false;
   is_cond = gimple_code (stmt) == GIMPLE_COND;
@@ -3958,7 +3958,7 @@  maybe_optimize_range_tests (gimple *stmt)
   else
     return cfg_cleanup_needed;
 
-  if (stmt_could_throw_p (stmt))
+  if (stmt_could_throw_p (cfun, stmt))
     return cfg_cleanup_needed;
 
   /* As relative ordering of post-dominator sons isn't fixed,
@@ -5109,14 +5109,14 @@  linearize_expr_tree (vec<operand_entry *> *ops, gimple *stmt,
     {
       binlhsdef = SSA_NAME_DEF_STMT (binlhs);
       binlhsisreassoc = (is_reassociable_op (binlhsdef, rhscode, loop)
-			 && !stmt_could_throw_p (binlhsdef));
+			 && !stmt_could_throw_p (cfun, binlhsdef));
     }
 
   if (TREE_CODE (binrhs) == SSA_NAME)
     {
       binrhsdef = SSA_NAME_DEF_STMT (binrhs);
       binrhsisreassoc = (is_reassociable_op (binrhsdef, rhscode, loop)
-			 && !stmt_could_throw_p (binrhsdef));
+			 && !stmt_could_throw_p (cfun, binrhsdef));
     }
 
   /* If the LHS is not reassociable, but the RHS is, we need to swap
@@ -5851,7 +5851,7 @@  reassociate_bb (basic_block bb)
       stmt = gsi_stmt (gsi);
 
       if (is_gimple_assign (stmt)
-	  && !stmt_could_throw_p (stmt))
+	  && !stmt_could_throw_p (cfun, stmt))
 	{
 	  tree lhs, rhs1, rhs2;
 	  enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 5a05dfb5640..e61f0ba7b8c 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1210,7 +1210,7 @@  copy_reference_ops_from_call (gcall *call,
   temp.opcode = CALL_EXPR;
   temp.op0 = gimple_call_fn (call);
   temp.op1 = gimple_call_chain (call);
-  if (stmt_could_throw_p (call) && (lr = lookup_stmt_eh_lp (call)) > 0)
+  if (stmt_could_throw_p (cfun, call) && (lr = lookup_stmt_eh_lp (call)) > 0)
     temp.op2 = size_int (lr);
   temp.off = -1;
   result->safe_push (temp);
diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c
index 9e751a27152..d1a73a5d64c 100644
--- a/gcc/tree-ssa-scopedtables.c
+++ b/gcc/tree-ssa-scopedtables.c
@@ -666,7 +666,7 @@  hashable_expr_equal_p (const struct hashable_expr *expr0,
                                  expr1->ops.call.args[i], 0))
             return false;
 
-	if (stmt_could_throw_p (expr0->ops.call.fn_from))
+	if (stmt_could_throw_p (cfun, expr0->ops.call.fn_from))
 	  {
 	    int lp0 = lookup_stmt_eh_lp (expr0->ops.call.fn_from);
 	    int lp1 = lookup_stmt_eh_lp (expr1->ops.call.fn_from);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 3fa5ef56f38..fd8c2750116 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1064,7 +1064,7 @@  adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
 
       if (!integer_zerop (gimple_assign_rhs1 (last.stmt)))
 	return;
-      if (stmt_could_throw_p (last.stmt))
+      if (stmt_could_throw_p (cfun, last.stmt))
 	return;
       gsi = gsi_for_stmt (last.stmt);
       unlink_stmt_vdef (last.stmt);
@@ -3253,7 +3253,7 @@  handle_char_store (gimple_stmt_iterator *gsi)
 	{
 	  /* When overwriting a '\0' with a '\0', the store can be removed
 	     if we know it has been stored in the current function.  */
-	  if (!stmt_could_throw_p (stmt) && si->writable)
+	  if (!stmt_could_throw_p (cfun, stmt) && si->writable)
 	    {
 	      unlink_stmt_vdef (stmt);
 	      release_defs (stmt);
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index c4805e72447..4b3711442e6 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -3844,7 +3844,7 @@  vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     return opt_result::failure_at (stmt, "not vectorized: volatile type: %G",
 				   stmt);
 
-  if (stmt_can_throw_internal (stmt))
+  if (stmt_can_throw_internal (cfun, stmt))
     return opt_result::failure_at (stmt,
 				   "not vectorized:"
 				   " statement can throw an exception: %G",
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 7956c1326d3..5548d47b87f 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -3235,7 +3235,7 @@  check_bool_pattern (tree var, vec_info *vinfo, hash_set<gimple *> &stmts)
 
 	  /* If the comparison can throw, then is_gimple_condexpr will be
 	     false and we can't make a COND_EXPR/VEC_COND_EXPR out of it.  */
-	  if (stmt_could_throw_p (def_stmt))
+	  if (stmt_could_throw_p (cfun, def_stmt))
 	    return false;
 
 	  comp_vectype = get_vectype_for_scalar_type (TREE_TYPE (rhs1));
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 8108d52a3cb..8995da80b1e 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1711,7 +1711,7 @@  vect_finish_stmt_generation_1 (stmt_vec_info stmt_info, gimple *vec_stmt)
      e.g. be in a must-not-throw region.  Ensure newly created stmts
      that could throw are part of the same region.  */
   int lp_nr = lookup_stmt_eh_lp (stmt_info->stmt);
-  if (lp_nr != 0 && stmt_could_throw_p (vec_stmt))
+  if (lp_nr != 0 && stmt_could_throw_p (cfun, vec_stmt))
     add_stmt_to_eh_lp (vec_stmt, lp_nr);
 
   return vec_stmt_info;
@@ -3116,7 +3116,7 @@  vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
       || TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
     return false;
 
-  gcc_checking_assert (!stmt_can_throw_internal (stmt));
+  gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
 
   vectype_out = STMT_VINFO_VECTYPE (stmt_info);
 
@@ -3751,7 +3751,7 @@  vectorizable_simd_clone_call (stmt_vec_info stmt_info,
       && TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
     return false;
 
-  gcc_checking_assert (!stmt_can_throw_internal (stmt));
+  gcc_checking_assert (!stmt_can_throw_internal (cfun, stmt));
 
   vectype = STMT_VINFO_VECTYPE (stmt_info);
 
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 60b982793d1..f3be9ff8747 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -1392,7 +1392,7 @@  gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
 
   /* Build an EH edge for the direct call if necessary.  */
   lp_nr = lookup_stmt_eh_lp (icall_stmt);
-  if (lp_nr > 0 && stmt_could_throw_p (dcall_stmt))
+  if (lp_nr > 0 && stmt_could_throw_p (cfun, dcall_stmt))
     {
       add_stmt_to_eh_lp (dcall_stmt, lp_nr);
     }
@@ -1410,7 +1410,7 @@  gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
 		     PHI_ARG_DEF_FROM_EDGE (phi, e_eh));
 	  }
        }
-  if (!stmt_could_throw_p (dcall_stmt))
+  if (!stmt_could_throw_p (cfun, dcall_stmt))
     gimple_purge_dead_eh_edges (dcall_bb);
   return dcall_stmt;
 }
@@ -1634,8 +1634,8 @@  gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, profile_probabi
     }
 
   /* Because these are all string op builtins, they're all nothrow.  */
-  gcc_assert (!stmt_could_throw_p (vcall_stmt));
-  gcc_assert (!stmt_could_throw_p (icall_stmt));
+  gcc_assert (!stmt_could_throw_p (cfun, vcall_stmt));
+  gcc_assert (!stmt_could_throw_p (cfun, icall_stmt));
 }
 
 /* Find values inside STMT for that we want to measure histograms for