> 2022-11-11  Martin Jambor  <mjam...@suse.cz>
> 
>       PR ipa/103227
>       * ipa-param-manipulation.h (class ipa_param_adjustments): Removed
>       member function get_updated_index_or_split.
>       (class ipa_param_body_adjustments): New overload of
>       register_replacement, new member function append_init_stmts, new
>       member m_split_agg_csts_inits.
>       * ipa-param-manipulation.cc: Include ipa-prop.h.
>       (ipa_param_adjustments::get_updated_index_or_split): Removed.
>       (ipa_param_body_adjustments::register_replacement): New overload, use
>       it from the older one.
>       (ipa_param_body_adjustments::common_initialization): Added the
>       capability to create replacements for conflicting IPA-CP discovered
>       constants.
>       (ipa_param_body_adjustments::ipa_param_body_adjustments): Construct
>       the new member.
>       (ipa_param_body_adjustments::append_init_stmts): New function.
>       * ipa-sra.cc: Include ipa-prop.h.
>       (push_param_adjustments_for_index): Require IPA-CP transformation
>       summary as a parameter, do not create replacements which are known to
>       have constant values.
>       (process_isra_node_results): Find and pass to the above function the
>       IPA-CP transformation summary.
>       * ipa-prop.cc (adjust_agg_replacement_values): Remove the
>       functionality replacing IPA-SRA created scalar parameters with
>       constants.  Simplify, do not require parameter descriptors, do not
>       return anything.
>       (ipcp_transform_function): Simplify now that
>       adjust_agg_replacement_values does not change cfg.  Move definition
>       and initialization of descriptors lower.
>       * tree-inline.cc (tree_function_versioning): Call append_init_stmts of
>       param_body_adjs, if there are any.
OK,
Honza
> 
> gcc/testsuite/ChangeLog:
> 
> 2022-11-11  Martin Jambor  <mjam...@suse.cz>
> 
>       PR ipa/103227
>       PR ipa/107640
>       * gcc.dg/ipa/pr107640-2.c: New test.
> ---
>  gcc/ipa-param-manipulation.cc         | 155 ++++++++++++++++----------
>  gcc/ipa-param-manipulation.h          |  19 ++--
>  gcc/ipa-prop.cc                       |  66 ++++-------
>  gcc/ipa-sra.cc                        |  30 ++++-
>  gcc/testsuite/gcc.dg/ipa/pr107640-2.c |  50 +++++++++
>  gcc/tree-inline.cc                    |   2 +
>  6 files changed, 208 insertions(+), 114 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/ipa/pr107640-2.c
> 
> diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc
> index cee0e23f946..e92cfc0b6d5 100644
> --- a/gcc/ipa-param-manipulation.cc
> +++ b/gcc/ipa-param-manipulation.cc
> @@ -46,7 +46,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-phinodes.h"
>  #include "cfgexpand.h"
>  #include "attribs.h"
> -
> +#include "ipa-prop.h"
>  
>  /* Actual prefixes of different newly synthetized parameters.  Keep in sync
>     with IPA_PARAM_PREFIX_* defines.  */
> @@ -449,39 +449,6 @@ ipa_param_adjustments::get_updated_indices (vec<int> 
> *new_indices)
>      }
>  }
>  
> -/* If a parameter with original INDEX has survived intact, return its new
> -   index.  Otherwise return -1.  In that case, if it has been split and there
> -   is a new parameter representing a portion at unit OFFSET for which a value
> -   of a TYPE can be substituted, store its new index into SPLIT_INDEX,
> -   otherwise store -1 there.  */
> -int
> -ipa_param_adjustments::get_updated_index_or_split (int index,
> -                                                unsigned unit_offset,
> -                                                tree type, int *split_index)
> -{
> -  unsigned adj_len = vec_safe_length (m_adj_params);
> -  for (unsigned i = 0; i < adj_len ; i++)
> -    {
> -      ipa_adjusted_param *apm = &(*m_adj_params)[i];
> -      if (apm->base_index != index)
> -     continue;
> -      if (apm->op == IPA_PARAM_OP_COPY)
> -     return i;
> -      if (apm->op == IPA_PARAM_OP_SPLIT
> -       && apm->unit_offset == unit_offset)
> -     {
> -       if (useless_type_conversion_p (apm->type, type))
> -         *split_index = i;
> -       else
> -         *split_index = -1;
> -       return -1;
> -     }
> -    }
> -
> -  *split_index = -1;
> -  return -1;
> -}
> -
>  /* Return the original index for the given new parameter index.  Return a
>     negative number if not available.  */
>  
> @@ -1020,6 +987,21 @@ ipa_param_adjustments::debug ()
>    dump (stderr);
>  }
>  
> +/* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET.  */
> +
> +void
> +ipa_param_body_adjustments::register_replacement (tree base,
> +                                               unsigned unit_offset,
> +                                               tree replacement)
> +{
> +  ipa_param_body_replacement psr;
> +  psr.base = base;
> +  psr.repl = replacement;
> +  psr.dummy = NULL_TREE;
> +  psr.unit_offset = unit_offset;
> +  m_replacements.safe_push (psr);
> +}
> +
>  /* Register that REPLACEMENT should replace parameter described in APM.  */
>  
>  void
> @@ -1029,12 +1011,8 @@ ipa_param_body_adjustments::register_replacement 
> (ipa_adjusted_param *apm,
>    gcc_checking_assert (apm->op == IPA_PARAM_OP_SPLIT
>                      || apm->op == IPA_PARAM_OP_NEW);
>    gcc_checking_assert (!apm->prev_clone_adjustment);
> -  ipa_param_body_replacement psr;
> -  psr.base = m_oparms[apm->prev_clone_index];
> -  psr.repl = replacement;
> -  psr.dummy = NULL_TREE;
> -  psr.unit_offset = apm->unit_offset;
> -  m_replacements.safe_push (psr);
> +  register_replacement (m_oparms[apm->prev_clone_index], apm->unit_offset,
> +                     replacement);
>  }
>  
>  /* Copy or not, as appropriate given m_id and decl context, a pre-existing
> @@ -1386,23 +1364,73 @@ ipa_param_body_adjustments::common_initialization 
> (tree old_fndecl,
>       gcc_unreachable ();
>      }
>  
> +  auto_vec <int, 16> index_mapping;
> +  bool need_remap = false;
> +  if (m_id)
> +    {
> +      clone_info *cinfo = clone_info::get (m_id->src_node);
> +      if (cinfo && cinfo->param_adjustments)
> +     {
> +       cinfo->param_adjustments->get_updated_indices (&index_mapping);
> +       need_remap = true;
> +     }
> +
> +      if (ipcp_transformation *ipcp_ts
> +       = ipcp_get_transformation_summary (m_id->src_node))
> +     {
> +       for (const ipa_argagg_value &av : ipcp_ts->m_agg_values)
> +         {
> +           int parm_num = av.index;
> +
> +           if (need_remap)
> +             {
> +               /* FIXME: We cannot handle the situation when IPA-CP
> +                  identified that a parameter is a pointer to a global
> +                  variable and at the same time the variable has some known
> +                  constant contents (PR 107640).  The best place to make
> +                  sure we don't drop such constants on the floor probably is
> +                  not here, but we have to make sure that it does not
> +                  confuse the remapping.  */
> +               if (parm_num >= (int) index_mapping.length ())
> +                 continue;
> +               parm_num = index_mapping[parm_num];
> +               if (parm_num < 0)
> +                 continue;
> +             }
> +
> +           if (!kept[parm_num])
> +             {
> +               /* IPA-CP has detected an aggregate constant in a parameter
> +                  that will not be kept, which means that IPA-SRA would have
> +                  split it if there wasn't a constant.  Because we are about
> +                  to remove the original, this is the last chance where we
> +                  can substitute the uses with a constant (for values passed
> +                  by reference) or do the split but initialize the
> +                  replacement with a constant (for split aggregates passed
> +                  by value).  */
> +
> +               tree repl;
> +               if (av.by_ref)
> +                 repl = av.value;
> +               else
> +                 {
> +                   repl = create_tmp_var (TREE_TYPE (av.value),
> +                                          "removed_ipa_cp");
> +                   gimple *init_stmt = gimple_build_assign (repl, av.value);
> +                   m_split_agg_csts_inits.safe_push (init_stmt);
> +                 }
> +               register_replacement (m_oparms[parm_num], av.unit_offset,
> +                                     repl);
> +               split[parm_num] = true;
> +             }
> +         }
> +     }
> +    }
> +
>    if (tree_map)
>      {
>        /* Do not treat parameters which were replaced with a constant as
>        completely vanished.  */
> -      auto_vec <int, 16> index_mapping;
> -      bool need_remap = false;
> -
> -      if (m_id)
> -     {
> -       clone_info *cinfo = clone_info::get (m_id->src_node);
> -       if (cinfo && cinfo->param_adjustments)
> -         {
> -           cinfo->param_adjustments->get_updated_indices (&index_mapping);
> -           need_remap = true;
> -         }
> -     }
> -
>        for (unsigned i = 0; i < tree_map->length (); i++)
>       {
>         int parm_num = (*tree_map)[i]->parm_num;
> @@ -1473,8 +1501,9 @@ ipa_param_body_adjustments
>    : m_adj_params (adj_params), m_adjustments (NULL), m_reset_debug_decls (),
>      m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (),
>      m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (),
> -    m_new_decls (), m_new_types (), m_replacements (), m_removed_decls (),
> -    m_removed_map (), m_method2func (false)
> +    m_new_decls (), m_new_types (), m_replacements (),
> +    m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
> +    m_method2func (false)
>  {
>    common_initialization (fndecl, NULL, NULL);
>  }
> @@ -1491,7 +1520,8 @@ ipa_param_body_adjustments
>      m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
>      m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
>      m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements 
> (),
> -    m_removed_decls (), m_removed_map (), m_method2func (false)
> +    m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
> +    m_method2func (false)
>  {
>    common_initialization (fndecl, NULL, NULL);
>  }
> @@ -1514,7 +1544,8 @@ ipa_param_body_adjustments
>      m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (),
>      m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl),
>      m_id (id), m_oparms (), m_new_decls (), m_new_types (), m_replacements 
> (),
> -    m_removed_decls (), m_removed_map (), m_method2func (false)
> +    m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (),
> +    m_method2func (false)
>  {
>    common_initialization (old_fndecl, vars, tree_map);
>  }
> @@ -2383,6 +2414,16 @@ 
> ipa_param_body_adjustments::perform_cfun_body_modifications ()
>  }
>  
>  
> +/* If there are any initialization statements that need to be emitted into
> +   the basic block BB right at ther start of the new function, do so.  */
> +void
> +ipa_param_body_adjustments::append_init_stmts (basic_block bb)
> +{
> +  gimple_stmt_iterator si = gsi_last_bb (bb);
> +  while (!m_split_agg_csts_inits.is_empty ())
> +    gsi_insert_after (&si, m_split_agg_csts_inits.pop (), GSI_NEW_STMT);
> +}
> +
>  /* Deallocate summaries which otherwise stay alive until the end of
>     compilation.  */
>  
> diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h
> index e5654f4ff70..e20d34918b3 100644
> --- a/gcc/ipa-param-manipulation.h
> +++ b/gcc/ipa-param-manipulation.h
> @@ -236,13 +236,6 @@ public:
>    void get_surviving_params (vec<bool> *surviving_params);
>    /* Fill a vector with new indices of surviving original parameters.  */
>    void get_updated_indices (vec<int> *new_indices);
> -  /* If a parameter with original INDEX has survived intact, return its new
> -     index.  Otherwise return -1.  In that case, if it has been split and 
> there
> -     is a new parameter representing a portion at UNIT_OFFSET for which a 
> value
> -     of a TYPE can be substituted, store its new index into SPLIT_INDEX,
> -     otherwise store -1 there.  */
> -  int get_updated_index_or_split (int index, unsigned unit_offset, tree type,
> -                               int *split_index);
>    /* Return the original index for the given new parameter index.  Return a
>       negative number if not available.  */
>    int get_original_index (int newidx);
> @@ -321,6 +314,8 @@ public:
>  
>    /* Change the PARM_DECLs.  */
>    void modify_formal_parameters ();
> +  /* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET.  */
> +  void register_replacement (tree base, unsigned unit_offset, tree 
> replacement);
>    /* Register a replacement decl for the transformation done in APM.  */
>    void register_replacement (ipa_adjusted_param *apm, tree replacement);
>    /* Lookup a replacement for a given offset within a given parameter.  */
> @@ -340,6 +335,10 @@ public:
>       they are mapped to.  */
>    void remap_with_debug_expressions (tree *t);
>  
> +  /* If there are any initialization statements that need to be emitted into
> +     the basic block BB right at ther start of the new function, do so.  */
> +  void append_init_stmts (basic_block bb);
> +
>    /* Pointers to data structures defining how the function should be
>       modified.  */
>    vec<ipa_adjusted_param, va_gc> *m_adj_params;
> @@ -405,6 +404,12 @@ private:
>  
>    auto_vec<ipa_param_body_replacement, 16> m_replacements;
>  
> +  /* List of initialization assignments to be put at the beginning of the
> +     cloned function to deal with split aggregates which however have known
> +     constant value and so their PARM_DECL disappears.  */
> +
> +  auto_vec<gimple *, 8> m_split_agg_csts_inits;
> +
>    /* Vector for remapping SSA_BASES from old parameter declarations that are
>       being removed as a part of the transformation.  Before a new VAR_DECL is
>       created, it holds the old PARM_DECL, once the variable is built it is
> diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
> index fcadf64ead7..08c7f97efb9 100644
> --- a/gcc/ipa-prop.cc
> +++ b/gcc/ipa-prop.cc
> @@ -5518,29 +5518,21 @@ ipcp_read_transformation_summaries (void)
>      }
>  }
>  
> -/* Adjust the aggregate replacements in TS to reflect parameters skipped in
> -   NODE but also if any parameter was IPA-SRAed into a scalar go ahead with
> -   substitution of the default_definitions of that new param with the
> -   appropriate constant.
> +/* Adjust the aggregate replacements in TS to reflect any parameter removals
> +   which might have already taken place.  If after adjustments there are no
> +   aggregate replacements left, the m_agg_values will be set to NULL.  In 
> other
> +   cases, it may be shrunk.  */
>  
> -   If after adjustments there are no aggregate replacements left, the
> -   m_agg_values will be set to NULL.  In other cases, it may be shrunk.
> -
> -   Return true if any values were already substituted for scalarized 
> parameters
> -   and update_cfg shuld be run after replace_uses_by.  */
> -
> -static bool
> -adjust_agg_replacement_values (cgraph_node *node,
> -                            ipcp_transformation *ts,
> -                            const vec<ipa_param_descriptor, va_gc>
> -                              &descriptors)
> +static void
> +adjust_agg_replacement_values (cgraph_node *node, ipcp_transformation *ts)
>  {
>    clone_info *cinfo = clone_info::get (node);
>    if (!cinfo || !cinfo->param_adjustments)
> -    return false;
> +    return;
>  
> +  auto_vec<int, 16> new_indices;
> +  cinfo->param_adjustments->get_updated_indices (&new_indices);
>    bool removed_item = false;
> -  bool done_replacement = false;
>    unsigned dst_index = 0;
>    unsigned count = ts->m_agg_values->length ();
>    for (unsigned i = 0; i < count; i++)
> @@ -5548,13 +5540,10 @@ adjust_agg_replacement_values (cgraph_node *node,
>        ipa_argagg_value *v = &(*ts->m_agg_values)[i];
>        gcc_checking_assert (v->index >= 0);
>  
> -      tree cst_type = TREE_TYPE (v->value);
> -      int split_idx;
> -      int new_idx
> -     = cinfo->param_adjustments->get_updated_index_or_split (v->index,
> -                                                             v->unit_offset,
> -                                                             cst_type,
> -                                                             &split_idx);
> +      int new_idx = -1;
> +      if ((unsigned) v->index < new_indices.length ())
> +     new_idx = new_indices[v->index];
> +
>        if (new_idx >= 0)
>       {
>         v->index = new_idx;
> @@ -5563,19 +5552,7 @@ adjust_agg_replacement_values (cgraph_node *node,
>         dst_index++;
>       }
>        else
> -     {
> -       removed_item = true;
> -       if (split_idx >= 0)
> -         {
> -           tree parm = ipa_get_param (descriptors, split_idx);
> -           tree ddef = ssa_default_def (cfun, parm);
> -           if (ddef)
> -             {
> -               replace_uses_by (ddef, v->value);
> -               done_replacement = true;
> -             }
> -         }
> -     }
> +     removed_item = true;
>      }
>  
>    if (dst_index == 0)
> @@ -5586,7 +5563,7 @@ adjust_agg_replacement_values (cgraph_node *node,
>    else if (removed_item)
>      ts->m_agg_values->truncate (dst_index);
>  
> -  return done_replacement;
> +  return;
>  }
>  
>  /* Dominator walker driving the ipcp modification phase.  */
> @@ -5955,7 +5932,6 @@ ipcp_update_vr (struct cgraph_node *node)
>  unsigned int
>  ipcp_transform_function (struct cgraph_node *node)
>  {
> -  vec<ipa_param_descriptor, va_gc> *descriptors = NULL;
>    struct ipa_func_body_info fbi;
>    int param_count;
>  
> @@ -5974,18 +5950,13 @@ ipcp_transform_function (struct cgraph_node *node)
>    param_count = count_formal_params (node->decl);
>    if (param_count == 0)
>      return 0;
> -  vec_safe_grow_cleared (descriptors, param_count, true);
> -  ipa_populate_param_decls (node, *descriptors);
>  
> -  bool cfg_changed = adjust_agg_replacement_values (node, ts, *descriptors);
> +  adjust_agg_replacement_values (node, ts);
>    if (vec_safe_is_empty (ts->m_agg_values))
>      {
> -      vec_free (descriptors);
>        if (dump_file)
>       fprintf (dump_file, "  All affected aggregate parameters were either "
>                "removed or converted into scalars, phase done.\n");
> -      if (cfg_changed)
> -     delete_unreachable_blocks_update_callgraph (node, false);
>        return 0;
>      }
>    if (dump_file)
> @@ -6002,12 +5973,15 @@ ipcp_transform_function (struct cgraph_node *node)
>    fbi.param_count = param_count;
>    fbi.aa_walk_budget = opt_for_fn (node->decl, param_ipa_max_aa_steps);
>  
> +  vec<ipa_param_descriptor, va_gc> *descriptors = NULL;
> +  vec_safe_grow_cleared (descriptors, param_count, true);
> +  ipa_populate_param_decls (node, *descriptors);
>    bool modified_mem_access = false;
>    calculate_dominance_info (CDI_DOMINATORS);
>    ipcp_modif_dom_walker walker (&fbi, descriptors, ts, &modified_mem_access);
>    walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
>    free_dominance_info (CDI_DOMINATORS);
> -  cfg_changed |= walker.cleanup_eh ();
> +  bool cfg_changed = walker.cleanup_eh ();
>  
>    int i;
>    struct ipa_bb_info *bi;
> diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
> index 718201d27fa..0f137e810fe 100644
> --- a/gcc/ipa-sra.cc
> +++ b/gcc/ipa-sra.cc
> @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "internal-fn.h"
>  #include "symtab-clones.h"
>  #include "attribs.h"
> +#include "ipa-prop.h"
>  
>  static void ipa_sra_summarize_function (cgraph_node *);
>  
> @@ -3605,13 +3606,16 @@ retval_used_p (cgraph_node *node, void *)
>  /* Push into NEW_PARAMS all required parameter adjustment entries to copy or
>     modify parameter which originally had index BASE_INDEX, in the adjustment
>     vector of parent clone (if any) had PREV_CLONE_INDEX and was described by
> -   PREV_ADJUSTMENT.  If the parent clone is the original function,
> -   PREV_ADJUSTMENT is NULL and PREV_CLONE_INDEX is equal to BASE_INDEX.  */
> +   PREV_ADJUSTMENT.  If IPA-CP has created a transformation summary for the
> +   original node, it needs to be passed in IPCP_TS, otherwise it should be
> +   NULL.  If the parent clone is the original function, PREV_ADJUSTMENT is 
> NULL
> +   and PREV_CLONE_INDEX is equal to BASE_INDEX.  */
>  
>  static void
>  push_param_adjustments_for_index (isra_func_summary *ifs, unsigned 
> base_index,
>                                 unsigned prev_clone_index,
>                                 ipa_adjusted_param *prev_adjustment,
> +                               ipcp_transformation *ipcp_ts,
>                                 vec<ipa_adjusted_param, va_gc> **new_params)
>  {
>    isra_param_desc *desc = &(*ifs->m_parameters)[base_index];
> @@ -3652,6 +3656,23 @@ push_param_adjustments_for_index (isra_func_summary 
> *ifs, unsigned base_index,
>        param_access *pa = (*desc->accesses)[j];
>        if (!pa->certain)
>       continue;
> +
> +      if (ipcp_ts)
> +     {
> +       ipa_argagg_value_list avl (ipcp_ts);
> +       tree value = avl.get_value (base_index, pa->unit_offset);
> +       if (value
> +           && (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value))) / BITS_PER_UNIT
> +               == pa->unit_size))
> +         {
> +           if (dump_file)
> +             fprintf (dump_file, "    - omitting component at byte "
> +                      "offset %u which is known to have a constant value\n ",
> +                      pa->unit_offset);
> +           continue;
> +         }
> +     }
> +
>        if (dump_file)
>       fprintf (dump_file, "    - component at byte offset %u, "
>                "size %u\n", pa->unit_offset, pa->unit_size);
> @@ -3732,6 +3753,7 @@ process_isra_node_results (cgraph_node *node,
>       fprintf (dump_file, "  Will remove return value.\n");
>      }
>  
> +  ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node);
>    vec<ipa_adjusted_param, va_gc> *new_params = NULL;
>    if (ipa_param_adjustments *old_adjustments
>        = cinfo ? cinfo->param_adjustments : NULL)
> @@ -3741,12 +3763,12 @@ process_isra_node_results (cgraph_node *node,
>       {
>         ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i];
>         push_param_adjustments_for_index (ifs, old_adj->base_index, i,
> -                                         old_adj, &new_params);
> +                                         old_adj, ipcp_ts, &new_params);
>       }
>      }
>    else
>      for (unsigned i = 0; i < param_count; i++)
> -      push_param_adjustments_for_index (ifs, i, i, NULL, &new_params);
> +      push_param_adjustments_for_index (ifs, i, i, NULL, ipcp_ts, 
> &new_params);
>  
>    ipa_param_adjustments *new_adjustments
>      = (new (ggc_alloc <ipa_param_adjustments> ())
> diff --git a/gcc/testsuite/gcc.dg/ipa/pr107640-2.c 
> b/gcc/testsuite/gcc.dg/ipa/pr107640-2.c
> new file mode 100644
> index 00000000000..94cbe02860d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/ipa/pr107640-2.c
> @@ -0,0 +1,50 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized-slim"  } */
> +
> +struct S
> +{
> +  int a, b, c;
> +};
> +
> +int ellide (int c);
> +volatile short gi;
> +
> +void __attribute__((noipa))
> +consume_s (struct S *p)
> +{
> +  gi = p->a;
> +}
> +
> +static void __attribute__((noinline))
> +foo (struct S *p, short *r)
> +{
> +  gi = *r;
> +  if (!__builtin_constant_p (p->b))
> +    ellide (1);
> +  consume_s (p);
> +}
> +
> +static void __attribute__((noinline))
> +bar (short *r, struct S *p)
> +{
> +  gi = *r;
> +  if (!__builtin_constant_p (p->c))
> +    ellide (2);
> +  consume_s (p);
> +}
> +
> +struct S gs;
> +
> +int main (int argc, char *argv[])
> +{
> +  short i = 42;
> +  gs.a = 10;
> +  gs.b = 20;
> +  foo (&gs, &i);
> +  gs.b = 30;
> +  gs.c = 40;
> +  bar (&i, &gs);
> +  return 0;
> +}
> +
> +/* { dg-final { scan-tree-dump-not "ellide" "optimized" { xfail *-*-* } } } 
> */
> diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
> index 8091ba8f13b..15a1a389493 100644
> --- a/gcc/tree-inline.cc
> +++ b/gcc/tree-inline.cc
> @@ -6377,6 +6377,8 @@ tree_function_versioning (tree old_decl, tree new_decl,
>    bb = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
>    while (init_stmts.length ())
>      insert_init_stmt (&id, bb, init_stmts.pop ());
> +  if (param_body_adjs)
> +    param_body_adjs->append_init_stmts (bb);
>    update_clone_info (&id);
>  
>    /* Remap the nonlocal_goto_save_area, if any.  */
> -- 
> 2.38.1
> 

Reply via email to