summaryrefslogtreecommitdiff
path: root/gcc/tree-eh.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2009-03-28 09:08:52 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2009-03-28 09:08:52 +0000
commita5bfef5b903f411fa79333e850b65d304835a159 (patch)
tree4ebe94b877890d5f85418fb99ec4730610bcb172 /gcc/tree-eh.c
parent86ecf8ad3e82852c1c5992e005c60409833f7549 (diff)
downloadgcc-a5bfef5b903f411fa79333e850b65d304835a159.tar.gz
* tree-eh.c (inlinable_call_p): New function.
(make_eh_edges): Use it. (verify_eh_edges): Use it. (stmt_can_throw_external, stmt_can_throw_internal): Use it. * except.c (reachable_next_level): Add inlinable_function argument (sjlj_find_directly_reachable_regions): Update. (add_reachable_handler): Do not set saw_any_handlers. (reachable_next_level): Handle MUST_NOT_THROW more curefully. (foreach_reachable_handler, can_throw_internal_1, can_throw_external_1): Add new inlinable call parameter. (can_throw_internal, can_throw_external): Update. * except.h (can_throw_internal_1, can_throw_external_1, foreach_reachable_handler): Update declaration. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145166 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r--gcc/tree-eh.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index e4fbaf7327c..c789acbd118 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1946,11 +1946,34 @@ make_eh_edge (struct eh_region *region, void *data)
make_edge (src, dst, EDGE_ABNORMAL | EDGE_EH);
}
+/* See if STMT is call that might be inlined. */
+
+static bool
+inlinable_call_p (gimple stmt)
+{
+ tree decl;
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ return false;
+ if (cfun->after_inlining)
+ return false;
+ /* Indirect calls can be propagated to direct call
+ and inlined. */
+ decl = gimple_call_fndecl (stmt);
+ if (!decl)
+ return true;
+ if (cgraph_function_flags_ready
+ && cgraph_function_body_availability (cgraph_node (decl))
+ < AVAIL_OVERWRITABLE)
+ return false;
+ return !DECL_UNINLINABLE (decl);
+}
+
void
make_eh_edges (gimple stmt)
{
int region_nr;
bool is_resx;
+ bool inlinable = false;
if (gimple_code (stmt) == GIMPLE_RESX)
{
@@ -1963,9 +1986,10 @@ make_eh_edges (gimple stmt)
if (region_nr < 0)
return;
is_resx = false;
+ inlinable = inlinable_call_p (stmt);
}
- foreach_reachable_handler (region_nr, is_resx, make_eh_edge, stmt);
+ foreach_reachable_handler (region_nr, is_resx, inlinable, make_eh_edge, stmt);
}
static bool mark_eh_edge_found_error;
@@ -2019,6 +2043,7 @@ verify_eh_edges (gimple stmt)
basic_block bb = gimple_bb (stmt);
edge_iterator ei;
edge e;
+ bool inlinable = false;
FOR_EACH_EDGE (e, ei, bb->succs)
gcc_assert (!e->aux);
@@ -2046,10 +2071,11 @@ verify_eh_edges (gimple stmt)
error ("BB %i last statement has incorrectly set region", bb->index);
return true;
}
+ inlinable = inlinable_call_p (stmt);
is_resx = false;
}
- foreach_reachable_handler (region_nr, is_resx, mark_eh_edge, stmt);
+ foreach_reachable_handler (region_nr, is_resx, inlinable, mark_eh_edge, stmt);
FOR_EACH_EDGE (e, ei, bb->succs)
{
if ((e->flags & EDGE_EH) && !e->aux)
@@ -2393,6 +2419,7 @@ stmt_can_throw_internal (gimple stmt)
{
int region_nr;
bool is_resx = false;
+ bool inlinable_call = false;
if (gimple_code (stmt) == GIMPLE_RESX)
{
@@ -2400,12 +2427,15 @@ stmt_can_throw_internal (gimple stmt)
is_resx = true;
}
else
- region_nr = lookup_stmt_eh_region (stmt);
+ {
+ region_nr = lookup_stmt_eh_region (stmt);
+ inlinable_call = inlinable_call_p (stmt);
+ }
if (region_nr < 0)
return false;
- return can_throw_internal_1 (region_nr, is_resx);
+ return can_throw_internal_1 (region_nr, is_resx, inlinable_call);
}