2014-06-03 13:07 GMT+04:00 Richard Biener <richard.guent...@gmail.com>: > On Mon, Jun 2, 2014 at 5:56 PM, Ilya Enkovich <enkovich....@gmail.com> wrote: >> Hi, >> >> This patch adds support for inlining instrumented calls. Changes are mostly >> to support returned bounds. Also generated mem-to-mem assignments are >> registered to be later instrumented with appropriate bounds copy. >> >> Bootstrapped and tested on linux-x86_64. >> >> Thanks, >> Ilya >> -- >> gcc/ >> >> 2014-06-02 Ilya Enkovich <ilya.enkov...@intel.com> >> >> * ipa-inline.c (early_inliner): Check edge has summary allocated. >> * tree-inline.c: Include tree-chkp.h. >> (declare_return_variable): Add arg holding >> returned bounds slot. Create and initialize returned bounds var. >> (remap_gimple_stmt): Handle returned bounds. >> Return sequence of statements instead of a single statement. >> (insert_init_stmt): Add declaration. >> (remap_gimple_seq): Adjust to new remap_gimple_stmt signature. >> (copy_bb): Adjust to changed return type of remap_gimple_stmt. >> (expand_call_inline): Handle returned bounds. Add bounds copy >> for generated mem to mem assignments. >> * tree-inline.h (copy_body_data): Add fields retbnd and >> assign_stmts. >> * cgraph.c: Include tree-chkp.h. >> (cgraph_redirect_edge_call_stmt_to_callee): Support >> returned bounds. >> * value-prof.c: Include tree-chkp.h. >> (gimple_ic): Support returned bounds. >> >> >> diff --git a/gcc/cgraph.c b/gcc/cgraph.c >> index 1f684c2..4b6996b 100644 >> --- a/gcc/cgraph.c >> +++ b/gcc/cgraph.c >> @@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see >> #include "gimple-pretty-print.h" >> #include "expr.h" >> #include "tree-dfa.h" >> +#include "tree-chkp.h" >> >> /* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about >> this. */ >> #include "tree-pass.h" >> @@ -1398,6 +1399,31 @@ cgraph_redirect_edge_call_stmt_to_callee (struct >> cgraph_edge *e) >> e->speculative = false; >> cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, >> new_stmt, false); >> + >> + /* Fix edges for BUILT_IN_CHKP_BNDRET calls attached to the >> + processed call stmt. */ >> + if (gimple_call_with_bounds_p (new_stmt) >> + && gimple_call_lhs (new_stmt) >> + && chkp_retbnd_call_by_val (gimple_call_lhs (e2->call_stmt))) >> + { >> + tree dresult = gimple_call_lhs (new_stmt); >> + tree iresult = gimple_call_lhs (e2->call_stmt); >> + gimple dbndret = chkp_retbnd_call_by_val (dresult); >> + gimple ibndret = chkp_retbnd_call_by_val (iresult); >> + struct cgraph_edge *iedge = cgraph_edge (e2->caller, ibndret); >> + struct cgraph_edge *dedge; >> + >> + if (dbndret) >> + { >> + dedge = cgraph_create_edge (iedge->caller, iedge->callee, >> + dbndret, e->count, >> + e->frequency); >> + dedge->frequency = compute_call_stmt_bb_frequency >> + (dedge->caller->decl, gimple_bb (dedge->call_stmt)); >> + } >> + iedge->frequency = compute_call_stmt_bb_frequency >> + (iedge->caller->decl, gimple_bb (iedge->call_stmt)); >> + } >> e->frequency = compute_call_stmt_bb_frequency >> (e->caller->decl, gimple_bb (e->call_stmt)); >> e2->frequency = compute_call_stmt_bb_frequency >> diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c >> index 4051819..a6fc853 100644 >> --- a/gcc/ipa-inline.c >> +++ b/gcc/ipa-inline.c >> @@ -2301,11 +2301,15 @@ early_inliner (void) >> info that might be cleared out for newly discovered edges. */ >> for (edge = node->callees; edge; edge = edge->next_callee) >> { >> - struct inline_edge_summary *es = inline_edge_summary (edge); >> - es->call_stmt_size >> - = estimate_num_insns (edge->call_stmt, &eni_size_weights); >> - es->call_stmt_time >> - = estimate_num_insns (edge->call_stmt, &eni_time_weights); >> + /* We have no summary for new bound store calls yet. */ >> + if (inline_edge_summary_vec.length () > (unsigned)edge->uid) >> + { >> + struct inline_edge_summary *es = inline_edge_summary >> (edge); >> + es->call_stmt_size >> + = estimate_num_insns (edge->call_stmt, >> &eni_size_weights); >> + es->call_stmt_time >> + = estimate_num_insns (edge->call_stmt, >> &eni_time_weights); >> + } >> if (edge->callee->decl >> && !gimple_check_call_matching_types ( >> edge->call_stmt, edge->callee->decl, false)) >> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c >> index 23fef90..6557a95 100644 >> --- a/gcc/tree-inline.c >> +++ b/gcc/tree-inline.c >> @@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see >> #include "tree-pass.h" >> #include "target.h" >> #include "cfgloop.h" >> +#include "tree-chkp.h" >> >> #include "rtl.h" /* FIXME: For asm_str_count. */ >> >> @@ -130,7 +131,8 @@ eni_weights eni_time_weights; >> >> /* Prototypes. */ >> >> -static tree declare_return_variable (copy_body_data *, tree, tree, >> basic_block); >> +static tree declare_return_variable (copy_body_data *, tree, tree, tree, >> + basic_block); >> static void remap_block (tree *, copy_body_data *); >> static void copy_bind_expr (tree *, int *, copy_body_data *); >> static void declare_inline_vars (tree, tree); >> @@ -139,8 +141,9 @@ static void prepend_lexical_block (tree current_block, >> tree new_block); >> static tree copy_decl_to_var (tree, copy_body_data *); >> static tree copy_result_decl_to_var (tree, copy_body_data *); >> static tree copy_decl_maybe_to_var (tree, copy_body_data *); >> -static gimple remap_gimple_stmt (gimple, copy_body_data *); >> +static gimple_seq remap_gimple_stmt (gimple, copy_body_data *); >> static bool delete_unreachable_blocks_update_callgraph (copy_body_data *id); >> +static void insert_init_stmt (copy_body_data *, basic_block, gimple); >> >> /* Insert a tree->tree mapping for ID. Despite the name suggests >> that the trees should be variables, it is used for more than that. */ >> @@ -732,8 +735,8 @@ remap_gimple_seq (gimple_seq body, copy_body_data *id) >> >> for (si = gsi_start (body); !gsi_end_p (si); gsi_next (&si)) >> { >> - gimple new_stmt = remap_gimple_stmt (gsi_stmt (si), id); >> - gimple_seq_add_stmt (&new_body, new_stmt); >> + gimple_seq new_stmts = remap_gimple_stmt (gsi_stmt (si), id); >> + gimple_seq_add_seq (&new_body, new_stmts); >> } >> >> return new_body; >> @@ -1241,12 +1244,13 @@ remap_eh_region_tree_nr (tree old_t_nr, >> copy_body_data *id) >> /* Helper for copy_bb. Remap statement STMT using the inlining >> information in ID. Return the new statement copy. */ >> >> -static gimple >> +static gimple_seq >> remap_gimple_stmt (gimple stmt, copy_body_data *id) >> { >> gimple copy = NULL; >> struct walk_stmt_info wi; >> bool skip_first = false; >> + gimple_seq stmts = NULL; >> >> /* Begin by recognizing trees that we'll completely rewrite for the >> inlining context. Our output for these trees is completely >> @@ -1261,6 +1265,17 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> if (gimple_code (stmt) == GIMPLE_RETURN && id->transform_return_to_modify) >> { >> tree retval = gimple_return_retval (stmt); >> + tree retbnd = gimple_return_retbnd (stmt); >> + tree bndslot = id->retbnd; >> + >> + if (retbnd && bndslot) >> + { >> + gimple bndcopy = gimple_build_assign (bndslot, retbnd); >> + memset (&wi, 0, sizeof (wi)); >> + wi.info = id; >> + walk_gimple_op (bndcopy, remap_gimple_op_r, &wi); >> + gimple_seq_add_stmt (&stmts, bndcopy); >> + } >> >> /* If we're returning something, just turn that into an >> assignment into the equivalent of the original RESULT_DECL. >> @@ -1278,9 +1293,18 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> retval); >> /* id->retvar is already substituted. Skip it on later remapping. >> */ >> skip_first = true; >> + >> + /* We need to copy bounds if return structure with pointers into >> + instrumented function. */ >> + if (chkp_function_instrumented_p (id->dst_fn) >> + && !bndslot >> + && !BOUNDED_P (id->retvar) >> + && chkp_type_has_pointer (TREE_TYPE (id->retvar))) >> + id->assign_stmts.safe_push (copy); >> + >> } >> else >> - return gimple_build_nop (); >> + return stmts; >> } >> else if (gimple_has_substatements (stmt)) >> { >> @@ -1444,7 +1468,7 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> value = *n; >> STRIP_TYPE_NOPS (value); >> if (TREE_CONSTANT (value) || TREE_READONLY (value)) >> - return gimple_build_nop (); >> + return NULL; >> } >> } >> >> @@ -1461,7 +1485,7 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> if (gimple_bb (def_stmt) >> && !bitmap_bit_p (id->blocks_to_copy, >> gimple_bb (def_stmt)->index)) >> - return gimple_build_nop (); >> + return NULL; >> } >> } >> >> @@ -1471,7 +1495,8 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> gimple_debug_bind_get_value (stmt), >> stmt); >> id->debug_stmts.safe_push (copy); >> - return copy; >> + gimple_seq_add_stmt (&stmts, copy); >> + return stmts; >> } >> if (gimple_debug_source_bind_p (stmt)) >> { >> @@ -1479,7 +1504,8 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> (gimple_debug_source_bind_get_var (stmt), >> gimple_debug_source_bind_get_value (stmt), stmt); >> id->debug_stmts.safe_push (copy); >> - return copy; >> + gimple_seq_add_stmt (&stmts, copy); >> + return stmts; >> } >> >> /* Create a new deep copy of the statement. */ >> @@ -1553,7 +1579,10 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> } >> >> if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy)) >> - return copy; >> + { >> + gimple_seq_add_stmt (&stmts, copy); >> + return stmts; >> + } >> >> /* Remap all the operands in COPY. */ >> memset (&wi, 0, sizeof (wi)); >> @@ -1571,7 +1600,8 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) >> gimple_set_vuse (copy, NULL_TREE); >> } >> >> - return copy; >> + gimple_seq_add_stmt (&stmts, copy); >> + return stmts; >> } >> >> >> @@ -1612,36 +1642,59 @@ copy_bb (copy_body_data *id, basic_block bb, int >> frequency_scale, >> >> for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >> { >> + gimple_seq stmts; >> gimple stmt = gsi_stmt (gsi); >> gimple orig_stmt = stmt; >> + gimple_stmt_iterator stmts_gsi; >> + bool stmt_added = false; >> >> id->regimplify = false; >> - stmt = remap_gimple_stmt (stmt, id); >> - if (gimple_nop_p (stmt)) >> + stmts = remap_gimple_stmt (stmt, id); >> + >> + if (gimple_seq_empty_p (stmts)) >> continue; >> >> - gimple_duplicate_stmt_histograms (cfun, stmt, id->src_cfun, >> orig_stmt); >> seq_gsi = copy_gsi; >> >> - /* With return slot optimization we can end up with >> - non-gimple (foo *)&this->m, fix that here. */ >> - if (is_gimple_assign (stmt) >> - && gimple_assign_rhs_code (stmt) == NOP_EXPR >> - && !is_gimple_val (gimple_assign_rhs1 (stmt))) >> + for (stmts_gsi = gsi_start (stmts); >> + !gsi_end_p (stmts_gsi); ) >> { >> - tree new_rhs; >> - new_rhs = force_gimple_operand_gsi (&seq_gsi, >> - gimple_assign_rhs1 (stmt), >> - true, NULL, false, >> - GSI_CONTINUE_LINKING); >> - gimple_assign_set_rhs1 (stmt, new_rhs); >> - id->regimplify = false; >> - } >> + stmt = gsi_stmt (stmts_gsi); >> + >> + /* Advance iterator now before stmt is moved to seq_gsi. */ >> + gsi_next (&stmts_gsi); >> + >> + if (gimple_nop_p (stmt)) >> + continue; >> + >> + gimple_duplicate_stmt_histograms (cfun, stmt, id->src_cfun, >> + orig_stmt); >> + >> + /* With return slot optimization we can end up with >> + non-gimple (foo *)&this->m, fix that here. */ >> + if (is_gimple_assign (stmt) >> + && gimple_assign_rhs_code (stmt) == NOP_EXPR >> + && !is_gimple_val (gimple_assign_rhs1 (stmt))) >> + { >> + tree new_rhs; >> + new_rhs = force_gimple_operand_gsi (&seq_gsi, >> + gimple_assign_rhs1 (stmt), >> + true, NULL, false, >> + GSI_CONTINUE_LINKING); >> + gimple_assign_set_rhs1 (stmt, new_rhs); >> + id->regimplify = false; >> + } >> >> - gsi_insert_after (&seq_gsi, stmt, GSI_NEW_STMT); >> + gsi_insert_after (&seq_gsi, stmt, GSI_NEW_STMT); >> >> - if (id->regimplify) >> - gimple_regimplify_operands (stmt, &seq_gsi); >> + if (id->regimplify) >> + gimple_regimplify_operands (stmt, &seq_gsi); >> + >> + stmt_added = true; >> + } >> + >> + if (!stmt_added) >> + continue; >> >> /* If copy_basic_block has been empty at the start of this iteration, >> call gsi_start_bb again to get at the newly added statements. */ >> @@ -3071,12 +3124,14 @@ initialize_inlined_parameters (copy_body_data *id, >> gimple stmt, >> is set only for CALL_EXPR_RETURN_SLOT_OPT. MODIFY_DEST, if non-null, >> was the LHS of the MODIFY_EXPR to which this call is the RHS. >> >> + RETURN_BOUNDS holds a destination for returned bounds. >> + >> The return value is a (possibly null) value that holds the result >> as seen by the caller. */ >> >> static tree >> declare_return_variable (copy_body_data *id, tree return_slot, tree >> modify_dest, >> - basic_block entry_bb) >> + tree return_bounds, basic_block entry_bb) >> { >> tree callee = id->src_fn; >> tree result = DECL_RESULT (callee); >> @@ -3255,6 +3310,19 @@ declare_return_variable (copy_body_data *id, tree >> return_slot, tree modify_dest, >> /* Remember this so we can ignore it in remap_decls. */ >> id->retvar = var; >> >> + /* If returned bounds are used, then make var for them. */ >> + if (return_bounds) >> + { >> + tree bndtemp = create_tmp_var (pointer_bounds_type_node, "retbnd"); >> + DECL_SEEN_IN_BIND_EXPR_P (bndtemp) = 1; >> + TREE_NO_WARNING (bndtemp) = 1; >> + declare_inline_vars (id->block, bndtemp); >> + >> + id->retbnd = bndtemp; >> + insert_init_stmt (id, entry_bb, >> + gimple_build_assign (bndtemp, chkp_get_zero_bounds_var >> ())); >> + } >> + >> return use; >> } >> >> @@ -4084,6 +4152,7 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> struct pointer_map_t *st, *dst; >> tree return_slot; >> tree modify_dest; >> + tree return_bounds = NULL; >> location_t saved_location; >> struct cgraph_edge *cg_edge; >> cgraph_inline_failed_t reason; >> @@ -4092,6 +4161,7 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> gimple_stmt_iterator gsi, stmt_gsi; >> bool successfully_inlined = FALSE; >> bool purge_dead_abnormal_edges; >> + unsigned int i; >> >> /* Set input_location here so we get the right instantiation context >> if we call instantiate_decl from inlinable_function_p. */ >> @@ -4180,6 +4250,7 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> >> /* We will be inlining this callee. */ >> id->eh_lp_nr = lookup_stmt_eh_lp (stmt); >> + id->assign_stmts.create (0); >> >> /* Update the callers EH personality. */ >> if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl)) >> @@ -4301,6 +4372,24 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> { >> modify_dest = gimple_call_lhs (stmt); >> >> + /* Remember where to copy returned bounds. */ >> + if (gimple_call_with_bounds_p (stmt) >> + && TREE_CODE (modify_dest) == SSA_NAME) >> + { >> + gimple retbnd = chkp_retbnd_call_by_val (modify_dest); >> + if (retbnd) >> + { >> + return_bounds = gimple_call_lhs (retbnd); >> + /* If returned bounds are not used then just >> + remove unused call. */ >> + if (!return_bounds) >> + { >> + gimple_stmt_iterator iter = gsi_for_stmt (retbnd); >> + gsi_remove (&iter, true); >> + } >> + } >> + } >> + >> /* The function which we are inlining might not return a value, >> in which case we should issue a warning that the function >> does not return a value. In that case the optimizers will >> @@ -4331,7 +4420,8 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> } >> >> /* Declare the return variable for the function. */ >> - use_retvar = declare_return_variable (id, return_slot, modify_dest, bb); >> + use_retvar = declare_return_variable (id, return_slot, modify_dest, >> + return_bounds, bb); >> >> /* Add local vars in this inlined callee to caller. */ >> add_local_variables (id->src_cfun, cfun, id); >> @@ -4383,6 +4473,12 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> stmt = gimple_build_assign (gimple_call_lhs (stmt), use_retvar); >> gsi_replace (&stmt_gsi, stmt, false); >> maybe_clean_or_replace_eh_stmt (old_stmt, stmt); >> + >> + /* Copy bounds if we copy structure with bounds. */ >> + if (chkp_function_instrumented_p (id->dst_fn) >> + && !BOUNDED_P (use_retvar) >> + && chkp_type_has_pointer (TREE_TYPE (use_retvar))) >> + id->assign_stmts.safe_push (stmt); >> } >> else >> { >> @@ -4414,6 +4510,20 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> gsi_remove (&stmt_gsi, true); >> } >> >> + /* Put returned bounds into the correct place if required. */ >> + if (return_bounds) >> + { >> + gimple old_stmt = SSA_NAME_DEF_STMT (return_bounds); >> + gimple new_stmt = gimple_build_assign (return_bounds, id->retbnd); >> + gimple_stmt_iterator bnd_gsi = gsi_for_stmt (old_stmt); >> + unlink_stmt_vdef (old_stmt); >> + gsi_replace (&bnd_gsi, new_stmt, false); >> + maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt); >> + cgraph_update_edges_for_call_stmt (old_stmt, >> + gimple_call_fndecl (old_stmt), >> + new_stmt); >> + } >> + >> if (purge_dead_abnormal_edges) >> { >> gimple_purge_dead_eh_edges (return_block); >> @@ -4430,6 +4540,11 @@ expand_call_inline (basic_block bb, gimple stmt, >> copy_body_data *id) >> TREE_USED (gimple_assign_rhs1 (stmt)) = 1; >> } >> >> + /* Copy bounds for all generated assigns that need it. */ >> + for (i = 0; i < id->assign_stmts.length (); i++) >> + chkp_copy_bounds_for_assign (id->assign_stmts[i], cg_edge); >> + id->assign_stmts.release (); >> + >> /* Output the inlining info for this abstract function, since it has been >> inlined. If we don't do this now, we can lose the information about >> the >> variables in the function when the blocks get blown away as soon as we >> diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h >> index 13c5516..a3b62b4 100644 >> --- a/gcc/tree-inline.h >> +++ b/gcc/tree-inline.h >> @@ -60,6 +60,12 @@ struct copy_body_data >> /* The VAR_DECL for the return value. */ >> tree retvar; >> >> + /* The VAR_DECL for the return bounds. */ >> + tree retbnd; >> + >> + /* Assign statements that need bounds copy. */ >> + vec<gimple> assign_stmts; >> + >> /* The map from local declarations in the inlined function to >> equivalents in the function into which it is being inlined. */ >> struct pointer_map_t *decl_map; >> diff --git a/gcc/value-prof.c b/gcc/value-prof.c >> index 2890093..5470167 100644 >> --- a/gcc/value-prof.c >> +++ b/gcc/value-prof.c >> @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see >> #include "data-streamer.h" >> #include "builtins.h" >> #include "tree-nested.h" >> +#include "tree-chkp.h" >> >> /* In this file value profile based optimizations are placed. Currently the >> following optimizations are implemented (for more detailed descriptions >> @@ -1319,7 +1320,7 @@ gimple >> gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, >> int prob, gcov_type count, gcov_type all) >> { >> - gimple dcall_stmt, load_stmt, cond_stmt; >> + gimple dcall_stmt, load_stmt, cond_stmt, iretbnd_stmt = NULL; >> tree tmp0, tmp1, tmp; >> basic_block cond_bb, dcall_bb, icall_bb, join_bb = NULL; >> tree optype = build_pointer_type (void_type_node); >> @@ -1333,6 +1334,9 @@ gimple_ic (gimple icall_stmt, struct cgraph_node >> *direct_call, >> cond_bb = gimple_bb (icall_stmt); >> gsi = gsi_for_stmt (icall_stmt); >> >> + if (gimple_call_with_bounds_p (icall_stmt) && gimple_call_lhs >> (icall_stmt)) >> + iretbnd_stmt = chkp_retbnd_call_by_val (gimple_call_lhs (icall_stmt)); >> + >> tmp0 = make_temp_ssa_name (optype, NULL, "PROF"); >> tmp1 = make_temp_ssa_name (optype, NULL, "PROF"); >> tmp = unshare_expr (gimple_call_fn (icall_stmt)); >> @@ -1425,6 +1429,49 @@ gimple_ic (gimple icall_stmt, struct cgraph_node >> *direct_call, >> gimple_call_set_lhs (dcall_stmt, >> duplicate_ssa_name (result, dcall_stmt)); >> add_phi_arg (phi, gimple_call_lhs (dcall_stmt), e_dj, >> UNKNOWN_LOCATION); >> + >> + /* If indirect call has following BUILT_IN_CHKP_BNDRET >> + call then we need to make it's copy for the direct >> + call. */ >> + if (iretbnd_stmt) >> + { >> + if (gimple_call_lhs (iretbnd_stmt)) >> + { >> + gimple copy; >> + >> + gimple_set_vdef (iretbnd_stmt, NULL_TREE); >> + gimple_set_vuse (iretbnd_stmt, NULL_TREE); >> + update_stmt (iretbnd_stmt); > > This looks bogus - what are you trying to workaround?
I did not try to workaround something. I just looked at how this function makes a copy for a call and repeated the process for retbnd call. > > Richard. > >> + result = gimple_call_lhs (iretbnd_stmt); >> + phi = create_phi_node (result, join_bb); >> + >> + copy = gimple_copy (iretbnd_stmt); >> + gimple_call_set_arg (copy, 0, >> + gimple_call_lhs (dcall_stmt)); >> + gimple_call_set_lhs (copy, duplicate_ssa_name (result, copy)); >> + gsi_insert_on_edge (e_dj, copy); >> + add_phi_arg (phi, gimple_call_lhs (copy), >> + e_dj, UNKNOWN_LOCATION); >> + >> + gimple_call_set_arg (iretbnd_stmt, 0, >> + gimple_call_lhs (icall_stmt)); >> + gimple_call_set_lhs (iretbnd_stmt, >> + duplicate_ssa_name (result, >> iretbnd_stmt)); >> + psi = gsi_for_stmt (iretbnd_stmt); >> + gsi_remove (&psi, false); >> + gsi_insert_on_edge (e_ij, iretbnd_stmt); >> + add_phi_arg (phi, gimple_call_lhs (iretbnd_stmt), >> + e_ij, UNKNOWN_LOCATION); >> + >> + gsi_commit_edge_inserts (); > > Are you sure this is a good idea? IMNSHO you should be using > either gsi_commit_one_edge_insert or be using gsi_insert_on_edge_immediate. Will replace it with a couple of gsi_commit_one_edge_insert. Thanks, Ilya > > Richard. > > >> + } >> + else >> + { >> + psi = gsi_for_stmt (iretbnd_stmt); >> + gsi_remove (&psi, true); >> + } >> + } >> } >> >> /* Build an EH edge for the direct call if necessary. */