aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-inline.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2009-09-14 12:18:58 -0700
committerRichard Henderson <rth@gcc.gnu.org>2009-09-14 12:18:58 -0700
commit1d65f45cfaefa060737af130c3fc69afb3030980 (patch)
tree2fcbbb5f99b13293753d83230cf9f4e0893a9b51 /gcc/tree-inline.c
parent0c433c31b31f25e3f18e58bd8d404c02722d7f7c (diff)
downloadgcc-1d65f45cfaefa060737af130c3fc69afb3030980.zip
gcc-1d65f45cfaefa060737af130c3fc69afb3030980.tar.gz
gcc-1d65f45cfaefa060737af130c3fc69afb3030980.tar.bz2
Squash commit of EH in gimple
From-SVN: r151696
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r--gcc/tree-inline.c179
1 files changed, 109 insertions, 70 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index b83c52f..5ada378 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -64,7 +64,7 @@ along with GCC; see the file COPYING3. If not see
MODIFY_EXPRs that store to a dedicated returned-value variable.
The duplicated eh_region info of the copy will later be appended
to the info for the caller; the eh_region info in copied throwing
- statements and RESX_EXPRs is adjusted accordingly.
+ statements and RESX statements are adjusted accordingly.
Cloning: (only in C++) We have one body for a con/de/structor, and
multiple function decls, each with a unique parameter list.
@@ -1105,12 +1105,6 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
TREE_BLOCK (*tp) = new_block;
}
- if (TREE_CODE (*tp) == RESX_EXPR && id->eh_region_offset)
- TREE_OPERAND (*tp, 0) =
- build_int_cst (NULL_TREE,
- id->eh_region_offset
- + TREE_INT_CST_LOW (TREE_OPERAND (*tp, 0)));
-
if (TREE_CODE (*tp) != OMP_CLAUSE)
TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
@@ -1150,6 +1144,35 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
+/* Helper for remap_gimple_stmt. Given an EH region number for the
+ source function, map that to the duplicate EH region number in
+ the destination function. */
+
+static int
+remap_eh_region_nr (int old_nr, copy_body_data *id)
+{
+ eh_region old_r, new_r;
+ void **slot;
+
+ old_r = get_eh_region_from_number_fn (id->src_cfun, old_nr);
+ slot = pointer_map_contains (id->eh_map, old_r);
+ new_r = (eh_region) *slot;
+
+ return new_r->index;
+}
+
+/* Similar, but operate on INTEGER_CSTs. */
+
+static tree
+remap_eh_region_tree_nr (tree old_t_nr, copy_body_data *id)
+{
+ int old_nr, new_nr;
+
+ old_nr = tree_low_cst (old_t_nr, 0);
+ new_nr = remap_eh_region_nr (old_nr, id);
+
+ return build_int_cst (NULL, new_nr);
+}
/* Helper for copy_bb. Remap statement STMT using the inlining
information in ID. Return the new statement copy. */
@@ -1339,9 +1362,59 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
VEC_safe_push (gimple, heap, id->debug_stmts, copy);
return copy;
}
- else
- /* Create a new deep copy of the statement. */
- copy = gimple_copy (stmt);
+
+ /* Create a new deep copy of the statement. */
+ copy = gimple_copy (stmt);
+
+ /* Remap the region numbers for __builtin_eh_{pointer,filter},
+ RESX and EH_DISPATCH. */
+ if (id->eh_map)
+ switch (gimple_code (copy))
+ {
+ case GIMPLE_CALL:
+ {
+ tree r, fndecl = gimple_call_fndecl (copy);
+ if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_EH_COPY_VALUES:
+ r = gimple_call_arg (copy, 1);
+ r = remap_eh_region_tree_nr (r, id);
+ gimple_call_set_arg (copy, 1, r);
+ /* FALLTHRU */
+
+ case BUILT_IN_EH_POINTER:
+ case BUILT_IN_EH_FILTER:
+ r = gimple_call_arg (copy, 0);
+ r = remap_eh_region_tree_nr (r, id);
+ gimple_call_set_arg (copy, 0, r);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case GIMPLE_RESX:
+ {
+ int r = gimple_resx_region (copy);
+ r = remap_eh_region_nr (r, id);
+ gimple_resx_set_region (copy, r);
+ }
+ break;
+
+ case GIMPLE_EH_DISPATCH:
+ {
+ int r = gimple_eh_dispatch_region (copy);
+ r = remap_eh_region_nr (r, id);
+ gimple_eh_dispatch_set_region (copy, r);
+ }
+ break;
+
+ default:
+ break;
+ }
}
/* If STMT has a block defined, map it to the newly constructed
@@ -1377,12 +1450,6 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
gimple_set_vuse (copy, NULL_TREE);
}
- /* We have to handle EH region remapping of GIMPLE_RESX specially because
- the region number is not an operand. */
- if (gimple_code (stmt) == GIMPLE_RESX && id->eh_region_offset)
- {
- gimple_resx_set_region (copy, gimple_resx_region (stmt) + id->eh_region_offset);
- }
return copy;
}
@@ -1617,43 +1684,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
cfun->calls_setjmp = true;
}
- /* If you think we can abort here, you are wrong.
- There is no region 0 in gimple. */
- gcc_assert (lookup_stmt_eh_region_fn (id->src_cfun, orig_stmt) != 0);
-
- if (stmt_could_throw_p (stmt)
- /* When we are cloning for inlining, we are supposed to
- construct a clone that calls precisely the same functions
- as original. However IPA optimizers might've proved
- earlier some function calls as non-trapping that might
- render some basic blocks dead that might become
- unreachable.
-
- We can't update SSA with unreachable blocks in CFG and thus
- we prevent the scenario by preserving even the "dead" eh
- edges until the point they are later removed by
- fixup_cfg pass. */
- || (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES
- && lookup_stmt_eh_region_fn (id->src_cfun, orig_stmt) > 0))
- {
- int region = lookup_stmt_eh_region_fn (id->src_cfun, orig_stmt);
-
- /* Add an entry for the copied tree in the EH hashtable.
- When cloning or versioning, use the hashtable in
- cfun, and just copy the EH number. When inlining, use the
- hashtable in the caller, and adjust the region number. */
- if (region > 0)
- add_stmt_to_eh_region (stmt, region + id->eh_region_offset);
-
- /* If this tree doesn't have a region associated with it,
- and there is a "current region,"
- then associate this tree with the current region
- and add edges associated with this region. */
- if (lookup_stmt_eh_region_fn (id->src_cfun, orig_stmt) <= 0
- && id->eh_region > 0
- && stmt_could_throw_p (stmt))
- add_stmt_to_eh_region (stmt, id->eh_region);
- }
+ maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt,
+ id->eh_map, id->eh_lp_nr);
if (gimple_in_ssa_p (cfun) && !is_gimple_debug (stmt))
{
@@ -1822,7 +1854,9 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
}
}
- if (can_throw)
+ if (gimple_code (copy_stmt) == GIMPLE_EH_DISPATCH)
+ make_eh_dispatch_edges (copy_stmt);
+ else if (can_throw)
make_eh_edges (copy_stmt);
if (nonlocal_goto)
@@ -2025,11 +2059,8 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
/* Duplicate any exception-handling regions. */
if (cfun->eh)
- {
- id->eh_region_offset
- = duplicate_eh_regions (cfun_to_copy, remap_decl_1, id,
- 0, id->eh_region);
- }
+ id->eh_map = duplicate_eh_regions (cfun_to_copy, NULL, id->eh_lp_nr,
+ remap_decl_1, id);
/* Use aux pointers to map the original blocks to copy. */
FOR_EACH_BB_FN (bb, cfun_to_copy)
@@ -2062,6 +2093,12 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency,
entry_block_map->aux = NULL;
exit_block_map->aux = NULL;
+ if (id->eh_map)
+ {
+ pointer_map_destroy (id->eh_map);
+ id->eh_map = NULL;
+ }
+
return new_fndecl;
}
@@ -3190,14 +3227,6 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
lhs = gimple_assign_lhs (stmt);
rhs = gimple_assign_rhs1 (stmt);
- /* EH magic stuff is most probably going to be optimized out.
- We rarely really need to save EH info for unwinding
- nested exceptions. */
- if (TREE_CODE (lhs) == FILTER_EXPR
- || TREE_CODE (lhs) == EXC_PTR_EXPR
- || TREE_CODE (rhs) == FILTER_EXPR
- || TREE_CODE (rhs) == EXC_PTR_EXPR)
- return 0;
if (is_gimple_reg (lhs))
cost = 0;
else
@@ -3308,9 +3337,19 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
return 0;
case GIMPLE_ASM:
- case GIMPLE_RESX:
return 1;
+ case GIMPLE_RESX:
+ /* This is either going to be an external function call with one
+ argument, or two register copy statements plus a goto. */
+ return 2;
+
+ case GIMPLE_EH_DISPATCH:
+ /* ??? This is going to turn into a switch statement. Ideally
+ we'd have a look at the eh region and estimate the number of
+ edges involved. */
+ return 10;
+
case GIMPLE_BIND:
return estimate_num_insns_seq (gimple_bind_body (stmt), weights);
@@ -3551,7 +3590,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
#endif
/* We will be inlining this callee. */
- id->eh_region = lookup_stmt_eh_region (stmt);
+ id->eh_lp_nr = lookup_stmt_eh_lp (stmt);
/* Update the callers EH personality. */
if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl))
@@ -4935,7 +4974,7 @@ maybe_inline_call_in_expr (tree exp)
id.do_not_unshare = true;
/* We're not inside any EH region. */
- id.eh_region = -1;
+ id.eh_lp_nr = 0;
t = copy_tree_body (&id);
pointer_map_destroy (decl_map);