diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-05-08 19:06:46 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-05-08 19:06:46 +0200 |
commit | ab87ac8d53f3d903bfc9eeb0f0b5e7eed1f38cbc (patch) | |
tree | 82cfaff6222e92d237be7a60aa9a5c1f2f835b38 /gcc/tree-inline.c | |
parent | 69708e0afbf3a3757b9f689bb54acff1d7e8d9ec (diff) | |
download | gcc-ab87ac8d53f3d903bfc9eeb0f0b5e7eed1f38cbc.zip gcc-ab87ac8d53f3d903bfc9eeb0f0b5e7eed1f38cbc.tar.gz gcc-ab87ac8d53f3d903bfc9eeb0f0b5e7eed1f38cbc.tar.bz2 |
re PR c++/59813 (tail-call elimination didn't fire for left-shift of char to cout)
PR c++/59813
PR tree-optimization/89060
* tree-ssa-live.h (live_vars_map): New typedef.
(compute_live_vars, live_vars_at_stmt, destroy_live_vars): Declare.
* tree-ssa-live.c: Include gimple-walk.h and cfganal.h.
(struct compute_live_vars_data): New type.
(compute_live_vars_visit, compute_live_vars_1, compute_live_vars,
live_vars_at_stmt, destroy_live_vars): New functions.
* tree-tailcall.c: Include tree-ssa-live.h.
(live_vars, live_vars_vec): New global variables.
(find_tail_calls): Perform variable life analysis before punting.
(tree_optimize_tail_calls_1): Clean up live_vars and live_vars_vec.
* tree-inline.h (struct copy_body_data): Add eh_landing_pad_dest
member.
* tree-inline.c (add_clobbers_to_eh_landing_pad): Remove BB argument.
Perform variable life analysis to select variables that really need
clobbers added.
(copy_edges_for_bb): Don't call add_clobbers_to_eh_landing_pad here,
instead set id->eh_landing_pad_dest and assert it is the same.
(copy_cfg_body): Call it here if id->eh_landing_pad_dest is non-NULL.
* gcc.dg/tree-ssa/pr89060.c: New test.
From-SVN: r271013
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 9bf1c40..2d314a7 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "sreal.h" #include "tree-cfgcleanup.h" +#include "tree-ssa-live.h" /* I'm not real happy about this, but we need to handle gimple and non-gimple trees. */ @@ -2285,12 +2286,15 @@ update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb, } /* Insert clobbers for automatic variables of inlined ID->src_fn - function at the start of basic block BB. */ + function at the start of basic block ID->eh_landing_pad_dest. */ static void -add_clobbers_to_eh_landing_pad (basic_block bb, copy_body_data *id) +add_clobbers_to_eh_landing_pad (copy_body_data *id) { tree var; + basic_block bb = id->eh_landing_pad_dest; + live_vars_map *vars = NULL; + unsigned int cnt = 0; unsigned int i; FOR_EACH_VEC_SAFE_ELT (id->src_cfun->local_decls, i, var) if (VAR_P (var) @@ -2312,12 +2316,47 @@ add_clobbers_to_eh_landing_pad (basic_block bb, copy_body_data *id) && !is_gimple_reg (new_var) && auto_var_in_fn_p (new_var, id->dst_fn)) { + if (vars == NULL) + vars = new live_vars_map; + vars->put (DECL_UID (var), cnt++); + } + } + if (vars == NULL) + return; + + vec<bitmap_head> live = compute_live_vars (id->src_cfun, vars); + FOR_EACH_VEC_SAFE_ELT (id->src_cfun->local_decls, i, var) + if (VAR_P (var)) + { + edge e; + edge_iterator ei; + bool needed = false; + unsigned int *v = vars->get (DECL_UID (var)); + if (v == NULL) + continue; + FOR_EACH_EDGE (e, ei, bb->preds) + if ((e->flags & EDGE_EH) != 0 + && e->src->index >= id->add_clobbers_to_eh_landing_pads) + { + basic_block src_bb = (basic_block) e->src->aux; + + if (bitmap_bit_p (&live[src_bb->index], *v)) + { + needed = true; + break; + } + } + if (needed) + { + tree new_var = *id->decl_map->get (var); gimple_stmt_iterator gsi = gsi_after_labels (bb); tree clobber = build_clobber (TREE_TYPE (new_var)); gimple *clobber_stmt = gimple_build_assign (new_var, clobber); gsi_insert_before (&gsi, clobber_stmt, GSI_NEW_STMT); } } + destroy_live_vars (live); + delete vars; } /* Copy edges from BB into its copy constructed earlier, scale profile @@ -2452,8 +2491,10 @@ copy_edges_for_bb (basic_block bb, profile_count num, profile_count den, e->probability = profile_probability::never (); if (e->dest->index < id->add_clobbers_to_eh_landing_pads) { - add_clobbers_to_eh_landing_pad (e->dest, id); - id->add_clobbers_to_eh_landing_pads = 0; + if (id->eh_landing_pad_dest == NULL) + id->eh_landing_pad_dest = e->dest; + else + gcc_assert (id->eh_landing_pad_dest == e->dest); } } } @@ -2893,6 +2934,12 @@ copy_cfg_body (copy_body_data * id, need_debug_cleanup |= copy_edges_for_bb (bb, num, den, exit_block_map, abnormal_goto_dest, id); + if (id->eh_landing_pad_dest) + { + add_clobbers_to_eh_landing_pad (id); + id->eh_landing_pad_dest = NULL; + } + if (new_entry) { edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, |