This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH, Pointer Bounds Checker 22/x] Inline
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Ilya Enkovich <enkovich dot gnu at gmail dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 3 Jun 2014 11:07:52 +0200
- Subject: Re: [PATCH, Pointer Bounds Checker 22/x] Inline
- Authentication-results: sourceware.org; auth=none
- References: <20140602153210 dot GE53659 at msticlxl57 dot ims dot intel dot com>
On Mon, Jun 2, 2014 at 5:56 PM, Ilya Enkovich <enkovich.gnu@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.enkovich@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?
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.
Richard.
> + }
> + else
> + {
> + psi = gsi_for_stmt (iretbnd_stmt);
> + gsi_remove (&psi, true);
> + }
> + }
> }
>
> /* Build an EH edge for the direct call if necessary. */