[PATCH] ipa-sra: Improve debug info for removed parameters (PR 93385)

Richard Biener rguenther@suse.de
Wed Nov 3 13:32:45 GMT 2021


On Mon, 1 Nov 2021, Martin Jambor wrote:

> Hello,
> 
> I'd like to ping this patch.
> 
> Thanks,
> 
> Martin
> 
> 
> On Wed, Oct 13 2021, Martin Jambor wrote:
> > Hi,
> >
> > in spring I added code eliminating any statements using parameters
> > removed by IPA passes (to fix PR 93385).  That patch fixed issues such
> > as divisions by zero that such code could perform but it only reset
> > all affected debug bind statements, this one updates them with
> > expressions which can allow the debugger to print the removed value -
> > see the added test-case for an example.
> >
> > Even though I originally did not want to create DEBUG_EXPR_DECLs for
> > intermediate values, I ended up doing so, because otherwise the code
> > started creating statements like
> >
> >    # DEBUG __aD.198693 => &MEM[(const struct _Alloc_nodeD.171110 *)D#195]._M_tD.184726->_M_implD.171154
> >
> > which not only is a bit scary but also gimple-fold ICEs on
> > it. Therefore I decided they are probably quite necessary.
> >
> > The patch simply notes each removed SSA name present in a debug
> > statement and then works from it backwards, looking if it can
> > reconstruct the expression it represents (which can fail if a
> > non-degenerate PHI node is in the way).  If it can, it populates two
> > hash maps with those expressions so that 1) removed assignments are
> > replaced with a debug bind defining a new intermediate debug_decl_expr
> > and 2) existing debug binds that refer to SSA names that are bing
> > removed now refer to corresponding debug_decl_exprs.
> >
> > If a removed parameter is passed to another function, the debugging
> > information still cannot describe its value there - see the xfailed
> > test in the testcase.  I sort of know what needs to be done but that
> > needs a little bit more of IPA infrastructure on top of this patch and
> > so I would like to get this patch reviewed first.
> >
> > Bootstrapped and tested on x86_64-linux, i686-linux and (long time
> > ago) on aarch64-linux.  Also LTO-bootstrapped and on x86_64-linux.
> >
> > Perhaps it is good to go to trunk?

I think the patch is OK for trunk.  It would be nice to common the

+      tree vexpr = make_node (DEBUG_EXPR_DECL);
+      DECL_ARTIFICIAL (vexpr) = 1;
+      TREE_TYPE (vexpr) = TREE_TYPE (val);
+      SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (val)));

blob that exists all over the GCC code base with a new
build_debug_expr_decl (tree type) (next to tree.c:build_decl).

Thanks,
Richard.

> > Thanks,
> >
> > Martin
> >
> > gcc/ChangeLog:
> >
> > 2021-03-29  Martin Jambor  <mjambor@suse.cz>
> >
> > 	PR ipa/93385
> > 	* ipa-param-manipulation.h (class ipa_param_body_adjustments): New
> > 	members remap_with_debug_expressions, m_dead_ssa_debug_equiv,
> > 	m_dead_stmt_debug_equiv and prepare_debug_expressions.  Added
> > 	parameter to mark_dead_statements.
> > 	* ipa-param-manipulation.c: Include tree-phinodes.h and cfgexpand.h.
> > 	(ipa_param_body_adjustments::mark_dead_statements): New parameter
> > 	debugstack, push into it all SSA names used in debug statements,
> > 	produce m_dead_ssa_debug_equiv mapping for the removed param.
> > 	(replace_with_mapped_expr): New function.
> > 	(ipa_param_body_adjustments::remap_with_debug_expressions): Likewise.
> > 	(ipa_param_body_adjustments::prepare_debug_expressions): Likewise.
> > 	(ipa_param_body_adjustments::common_initialization): Gather and
> > 	procecc SSA which will be removed but are in debug statements. Simplify.
> > 	(ipa_param_body_adjustments::ipa_param_body_adjustments): Initialize
> > 	new members.
> > 	* tree-inline.c (remap_gimple_stmt): Create a debug bind when possible
> > 	when avoiding a copy of an unnecessary statement.  Remap removed SSA
> > 	names in existing debug statements.
> > 	(tree_function_versioning): Do not create DEBUG_EXPR_DECL for removed
> > 	parameters if we have already done so.
> >
> > gcc/testsuite/ChangeLog:
> >
> > 2021-03-29  Martin Jambor  <mjambor@suse.cz>
> >
> > 	PR ipa/93385
> > 	* gcc.dg/guality/ipa-sra-1.c: New test.
> > ---
> >  gcc/ipa-param-manipulation.c             | 280 ++++++++++++++++++-----
> >  gcc/ipa-param-manipulation.h             |  12 +-
> >  gcc/testsuite/gcc.dg/guality/ipa-sra-1.c |  45 ++++
> >  gcc/tree-inline.c                        |  45 ++--
> >  4 files changed, 305 insertions(+), 77 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/guality/ipa-sra-1.c
> >
> > diff --git a/gcc/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
> > index 26b02d7aa95..c84d669521c 100644
> > --- a/gcc/ipa-param-manipulation.c
> > +++ b/gcc/ipa-param-manipulation.c
> > @@ -43,6 +43,8 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "alloc-pool.h"
> >  #include "symbol-summary.h"
> >  #include "symtab-clones.h"
> > +#include "tree-phinodes.h"
> > +#include "cfgexpand.h"
> >  
> >  
> >  /* Actual prefixes of different newly synthetized parameters.  Keep in sync
> > @@ -972,10 +974,12 @@ ipa_param_body_adjustments::carry_over_param (tree t)
> >  
> >  /* Populate m_dead_stmts given that DEAD_PARAM is going to be removed without
> >     any replacement or splitting.  REPL is the replacement VAR_SECL to base any
> > -   remaining uses of a removed parameter on.  */
> > +   remaining uses of a removed parameter on.  Push all removed SSA names that
> > +   are used within debug statements to DEBUGSTACK.  */
> >  
> >  void
> > -ipa_param_body_adjustments::mark_dead_statements (tree dead_param)
> > +ipa_param_body_adjustments::mark_dead_statements (tree dead_param,
> > +						  vec<tree> *debugstack)
> >  {
> >    /* Current IPA analyses which remove unused parameters never remove a
> >       non-gimple register ones which have any use except as parameters in other
> > @@ -987,6 +991,7 @@ ipa_param_body_adjustments::mark_dead_statements (tree dead_param)
> >      return;
> >  
> >    auto_vec<tree, 4> stack;
> > +  hash_set<tree> used_in_debug;
> >    m_dead_ssas.add (parm_ddef);
> >    stack.safe_push (parm_ddef);
> >    while (!stack.is_empty ())
> > @@ -1014,6 +1019,11 @@ ipa_param_body_adjustments::mark_dead_statements (tree dead_param)
> >  	    {
> >  	      m_dead_stmts.add (stmt);
> >  	      gcc_assert (gimple_debug_bind_p (stmt));
> > +	      if (!used_in_debug.contains (t))
> > +		{
> > +		  used_in_debug.add (t);
> > +		  debugstack->safe_push (t);
> > +		}
> >  	    }
> >  	  else if (gimple_code (stmt) == GIMPLE_PHI)
> >  	    {
> > @@ -1046,6 +1056,149 @@ ipa_param_body_adjustments::mark_dead_statements (tree dead_param)
> >  	    gcc_unreachable ();
> >  	}
> >      }
> > +
> > +  if (!MAY_HAVE_DEBUG_STMTS)
> > +    {
> > +      gcc_assert (debugstack->is_empty ());
> > +      return;
> > +    }
> > +
> > +  tree dp_ddecl = make_node (DEBUG_EXPR_DECL);
> > +  DECL_ARTIFICIAL (dp_ddecl) = 1;
> > +  TREE_TYPE (dp_ddecl) = TREE_TYPE (dead_param);
> > +  SET_DECL_MODE (dp_ddecl, DECL_MODE (dead_param));
> > +  m_dead_ssa_debug_equiv.put (parm_ddef, dp_ddecl);
> > +}
> > +
> > +/* Callback to walk_tree.  If REMAP is an SSA_NAME that is present in hash_map
> > +   passed in DATA, replace it with unshared version of what it was mapped
> > +   to.  */
> > +
> > +static tree
> > +replace_with_mapped_expr (tree *remap, int *walk_subtrees, void *data)
> > +{
> > +  if (TYPE_P (*remap))
> > +    {
> > +      *walk_subtrees = 0;
> > +      return 0;
> > +    }
> > +  if (TREE_CODE (*remap) != SSA_NAME)
> > +    return 0;
> > +
> > +  *walk_subtrees = 0;
> > +
> > +  hash_map<tree, tree> *equivs = (hash_map<tree, tree> *) data;
> > +  if (tree *p = equivs->get (*remap))
> > +    *remap = unshare_expr (*p);
> > +  return 0;
> > +}
> > +
> > +/* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what they
> > +   are mapped to.  */
> > +
> > +void
> > +ipa_param_body_adjustments::remap_with_debug_expressions (tree *t)
> > +{
> > +  /* If *t is an SSA_NAME which should have its debug statements reset, it is
> > +     mapped to NULL in the hash_map.  We need to handle that case separately or
> > +     otherwise the walker would segfault.  No expression that is more
> > +     complicated than that can have its operands mapped to NULL.  */
> > +  if (TREE_CODE (*t) == SSA_NAME)
> > +    {
> > +      if (tree *p = m_dead_ssa_debug_equiv.get (*t))
> > +	*t = *p;
> > +    }
> > +  else
> > +    walk_tree (t, replace_with_mapped_expr, &m_dead_ssa_debug_equiv, NULL);
> > +}
> > +
> > +/* For an SSA_NAME DEAD_SSA which is about to be DCEd because it is based on a
> > +   useless parameter, prepare an expression that should represent it in
> > +   debug_binds in the cloned function and add a mapping from DEAD_SSA to
> > +   m_dead_ssa_debug_equiv.  That mapping is to NULL when the associated
> > +   debug_statement has to be reset instead.  In such case return false,
> > +   ottherwise return true.  If DEAD_SSA comes from a basic block which is not
> > +   about to be copied, ignore it and return true.  */
> > +
> > +bool
> > +ipa_param_body_adjustments::prepare_debug_expressions (tree dead_ssa)
> > +{
> > +  gcc_checking_assert (m_dead_ssas.contains (dead_ssa));
> > +  if (tree *d = m_dead_ssa_debug_equiv.get (dead_ssa))
> > +    return (*d != NULL_TREE);
> > +
> > +  gcc_assert (!SSA_NAME_IS_DEFAULT_DEF (dead_ssa));
> > +  gimple *def = SSA_NAME_DEF_STMT (dead_ssa);
> > +  if (m_id->blocks_to_copy
> > +      && !bitmap_bit_p (m_id->blocks_to_copy, gimple_bb (def)->index))
> > +    return true;
> > +
> > +  if (gimple_code (def) == GIMPLE_PHI)
> > +    {
> > +      /* In theory, we could ignore all SSAs coming from BBs not in
> > +	 m_id->blocks_to_copy but at the time of the writing this code that
> > +	 should never really be the case because only fnsplit uses that bitmap,
> > +	 so don't bother.  */
> > +      tree value = degenerate_phi_result (as_a <gphi *> (def));
> > +      if (!value
> > +	  || (m_dead_ssas.contains (value)
> > +	      && !prepare_debug_expressions (value)))
> > +	{
> > +	  m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
> > +	  return false;
> > +	}
> > +
> > +      gcc_assert (TREE_CODE (value) == SSA_NAME);
> > +      tree *d = m_dead_ssa_debug_equiv.get (value);
> > +      m_dead_ssa_debug_equiv.put (dead_ssa, *d);
> > +      return true;
> > +    }
> > +
> > +  bool lost = false;
> > +  use_operand_p use_p;
> > +  ssa_op_iter oi;
> > +  FOR_EACH_PHI_OR_STMT_USE (use_p, def, oi, SSA_OP_USE)
> > +    {
> > +      tree use = USE_FROM_PTR (use_p);
> > +      if (m_dead_ssas.contains (use)
> > +	  && !prepare_debug_expressions (use))
> > +	{
> > +	  lost = true;
> > +	  break;
> > +	}
> > +    }
> > +
> > +  if (lost)
> > +    {
> > +      m_dead_ssa_debug_equiv.put (dead_ssa, NULL_TREE);
> > +      return false;
> > +    }
> > +
> > +  if (is_gimple_assign (def))
> > +    {
> > +      gcc_assert (!gimple_clobber_p (def));
> > +      if (gimple_assign_copy_p (def)
> > +	  && TREE_CODE (gimple_assign_rhs1 (def)) == SSA_NAME)
> > +	{
> > +	  tree *d = m_dead_ssa_debug_equiv.get (gimple_assign_rhs1 (def));
> > +	  m_dead_ssa_debug_equiv.put (dead_ssa, *d);
> > +	  return (*d != NULL_TREE);
> > +	}
> > +
> > +      tree val = gimple_assign_rhs_to_tree (def);
> > +      SET_EXPR_LOCATION (val, UNKNOWN_LOCATION);
> > +      remap_with_debug_expressions (&val);
> > +
> > +      tree vexpr = make_node (DEBUG_EXPR_DECL);
> > +      DECL_ARTIFICIAL (vexpr) = 1;
> > +      TREE_TYPE (vexpr) = TREE_TYPE (val);
> > +      SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (val)));
> > +      m_dead_stmt_debug_equiv.put (def, val);
> > +      m_dead_ssa_debug_equiv.put (dead_ssa, vexpr);
> > +      return true;
> > +    }
> > +  else
> > +    gcc_unreachable ();
> >  }
> >  
> >  /* Common initialization performed by all ipa_param_body_adjustments
> > @@ -1137,65 +1290,21 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
> >  	gcc_unreachable ();
> >      }
> >  
> > -
> > -  /* As part of body modifications, we will also have to replace remaining uses
> > -     of remaining uses of removed PARM_DECLs (which do not however use the
> > -     initial value) with their VAR_DECL copies.
> > -
> > -     We do this differently with and without m_id.  With m_id, we rely on its
> > -     mapping and create a replacement straight away.  Without it, we have our
> > -     own mechanism for which we have to populate m_removed_decls vector.  Just
> > -     don't mix them, that is why you should not call
> > -     replace_removed_params_ssa_names or perform_cfun_body_modifications when
> > -     you construct with ID not equal to NULL.  */
> > -
> > -  unsigned op_len = m_oparms.length ();
> > -  for (unsigned i = 0; i < op_len; i++)
> > -    if (!kept[i])
> > -      {
> > -	if (m_id)
> > -	  {
> > -	    if (!m_id->decl_map->get (m_oparms[i]))
> > -	      {
> > -		tree var = copy_decl_to_var (m_oparms[i], m_id);
> > -		insert_decl_map (m_id, m_oparms[i], var);
> > -		/* Declare this new variable.  */
> > -		DECL_CHAIN (var) = *vars;
> > -		*vars = var;
> > -
> > -		/* If this is not a split but a real removal, init hash sets
> > -		   that will guide what not to copy to the new body.  */
> > -		if (!split[i])
> > -		  mark_dead_statements (m_oparms[i]);
> > -	      }
> > -	  }
> > -	else
> > -	  {
> > -	    m_removed_decls.safe_push (m_oparms[i]);
> > -	    m_removed_map.put (m_oparms[i], m_removed_decls.length () - 1);
> > -	  }
> > -      }
> > -
> > -  if (!MAY_HAVE_DEBUG_STMTS)
> > -    return;
> > -
> > -  /* Finally, when generating debug info, we fill vector m_reset_debug_decls
> > -    with removed parameters declarations.  We do this in order to re-map their
> > -    debug bind statements and create debug decls for them.  */
> > -
> >    if (tree_map)
> >      {
> > -      /* Do not output debuginfo for parameter declarations as if they vanished
> > -	 when they were in fact replaced by a constant.  */
> > +      /* Do not treat parameters which were replaced with a constant as
> > +	 completely vanished.  */
> >        auto_vec <int, 16> index_mapping;
> >        bool need_remap = false;
> > -      clone_info *info = clone_info::get (m_id->src_node);
> >  
> > -      if (m_id && info && info->param_adjustments)
> > +      if (m_id)
> >  	{
> > -	  ipa_param_adjustments *prev_adjustments = info->param_adjustments;
> > -	  prev_adjustments->get_updated_indices (&index_mapping);
> > -	  need_remap = true;
> > +	  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++)
> > @@ -1208,9 +1317,52 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
> >  	}
> >      }
> >  
> > +  /* As part of body modifications, we will also have to replace remaining uses
> > +     of remaining uses of removed PARM_DECLs (which do not however use the
> > +     initial value) with their VAR_DECL copies.
> > +
> > +     We do this differently with and without m_id.  With m_id, we rely on its
> > +     mapping and create a replacement straight away.  Without it, we have our
> > +     own mechanism for which we have to populate m_removed_decls vector.  Just
> > +     don't mix them, that is why you should not call
> > +     replace_removed_params_ssa_names or perform_cfun_body_modifications when
> > +     you construct with ID not equal to NULL.  */
> > +
> > +  auto_vec<tree, 8> ssas_to_process_debug;
> > +  unsigned op_len = m_oparms.length ();
> >    for (unsigned i = 0; i < op_len; i++)
> > -    if (!kept[i] && is_gimple_reg (m_oparms[i]))
> > -      m_reset_debug_decls.safe_push (m_oparms[i]);
> > +    if (!kept[i])
> > +      {
> > +	if (m_id)
> > +	  {
> > +	    gcc_assert (!m_id->decl_map->get (m_oparms[i]));
> > +	    tree var = copy_decl_to_var (m_oparms[i], m_id);
> > +	    insert_decl_map (m_id, m_oparms[i], var);
> > +	    /* Declare this new variable.  */
> > +	    DECL_CHAIN (var) = *vars;
> > +	    *vars = var;
> > +
> > +	    /* If this is not a split but a real removal, init hash sets
> > +	       that will guide what not to copy to the new body.  */
> > +	    if (!split[i])
> > +	      mark_dead_statements (m_oparms[i], &ssas_to_process_debug);
> > +	    if (MAY_HAVE_DEBUG_STMTS
> > +		&& is_gimple_reg (m_oparms[i]))
> > +	      m_reset_debug_decls.safe_push (m_oparms[i]);
> > +	  }
> > +	else
> > +	  {
> > +	    m_removed_decls.safe_push (m_oparms[i]);
> > +	    m_removed_map.put (m_oparms[i], m_removed_decls.length () - 1);
> > +	    if (MAY_HAVE_DEBUG_STMTS
> > +		&& !kept[i]
> > +		&& is_gimple_reg (m_oparms[i]))
> > +	      m_reset_debug_decls.safe_push (m_oparms[i]);
> > +	  }
> > +      }
> > +
> > +  while (!ssas_to_process_debug.is_empty ())
> > +    prepare_debug_expressions (ssas_to_process_debug.pop ());
> >  }
> >  
> >  /* Constructor of ipa_param_body_adjustments from a simple list of
> > @@ -1224,9 +1376,9 @@ ipa_param_body_adjustments
> >  			      tree fndecl)
> >    : m_adj_params (adj_params), m_adjustments (NULL), m_reset_debug_decls (),
> >      m_split_modifications_p (false), m_dead_stmts (), m_dead_ssas (),
> > -    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_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)
> >  {
> >    common_initialization (fndecl, NULL, NULL);
> >  }
> > @@ -1241,7 +1393,8 @@ ipa_param_body_adjustments
> >  			      tree fndecl)
> >    : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
> >      m_reset_debug_decls (), m_split_modifications_p (false), m_dead_stmts (),
> > -    m_dead_ssas (), m_fndecl (fndecl), m_id (NULL), m_oparms (), m_new_decls (),
> > +    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)
> >  {
> > @@ -1264,8 +1417,9 @@ ipa_param_body_adjustments
> >  			      vec<ipa_replace_map *, va_gc> *tree_map)
> >    : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments),
> >      m_reset_debug_decls (), m_split_modifications_p (false), m_dead_stmts (),
> > -    m_dead_ssas (),m_fndecl (fndecl), m_id (id), m_oparms (), m_new_decls (),
> > -    m_new_types (), m_replacements (), m_removed_decls (), m_removed_map (),
> > +    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)
> >  {
> >    common_initialization (old_fndecl, vars, tree_map);
> > diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h
> > index afcbc09bf33..9440cbfc56c 100644
> > --- a/gcc/ipa-param-manipulation.h
> > +++ b/gcc/ipa-param-manipulation.h
> > @@ -328,6 +328,9 @@ public:
> >  			   gimple *orig_stmt);
> >    /* Return the new chain of parameters.  */
> >    tree get_new_param_chain ();
> > +  /* Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what
> > +     they are mapped to.  */
> > +  void remap_with_debug_expressions (tree *t);
> >  
> >    /* Pointers to data structures defining how the function should be
> >       modified.  */
> > @@ -348,6 +351,12 @@ public:
> >    hash_set<gimple *> m_dead_stmts;
> >    hash_set<tree> m_dead_ssas;
> >  
> > +  /* Mapping from DCEd SSAs to what their potential debug_binds should be.  */
> > +  hash_map<tree, tree> m_dead_ssa_debug_equiv;
> > +  /* Mapping from DCEd statements to debug expressions that will be placed on
> > +     the RHS of debug statement that will replace this one.  */
> > +  hash_map<gimple *, tree> m_dead_stmt_debug_equiv;
> > +
> >  private:
> >    void common_initialization (tree old_fndecl, tree *vars,
> >  			      vec<ipa_replace_map *, va_gc> *tree_map);
> > @@ -361,7 +370,8 @@ private:
> >    bool modify_call_stmt (gcall **stmt_p, gimple *orig_stmt);
> >    bool modify_cfun_body ();
> >    void reset_debug_stmts ();
> > -  void mark_dead_statements (tree dead_param);
> > +  void mark_dead_statements (tree dead_param, vec<tree> *debugstack);
> > +  bool prepare_debug_expressions (tree dead_ssa);
> >  
> >    /* Declaration of the function that is being transformed.  */
> >  
> > diff --git a/gcc/testsuite/gcc.dg/guality/ipa-sra-1.c b/gcc/testsuite/gcc.dg/guality/ipa-sra-1.c
> > new file mode 100644
> > index 00000000000..5434b3d7665
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/guality/ipa-sra-1.c
> > @@ -0,0 +1,45 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-g -fno-ipa-icf" } */
> > +
> > +
> > +void __attribute__((noipa))
> > +use (int x)
> > +{
> > +  asm volatile ("" : : "r" (x) : "memory");
> > +}
> > +
> > +static int __attribute__((noinline))
> > +bar (int i, int k)
> > +{
> > +  asm ("" : "+r" (i));
> > +  use (i);		/* { dg-final { gdb-test . "k" "3" { xfail *-*-* } } } */
> > +  return 6;
> > +}
> > +
> > +volatile int v;
> > +
> > +static int __attribute__((noinline))
> > +foo (int i, int k)
> > +{
> > +  int r;
> > +  v = 9;
> > +  k = (k + 14)/k;
> > +  r = bar (i, k);		/* { dg-final { gdb-test . "k" "3" } } */
> > +  return r;
> > +}
> > +
> > +volatile int v;
> > +
> > +int __attribute__((noipa))
> > +get_val1 (void)  {return 20;}
> > +int __attribute__((noipa))
> > +get_val2 (void)  {return 7;}
> > +
> > +int
> > +main (void)
> > +{
> > +  int k = get_val2 ();
> > +  int r = foo (get_val1 (), k);
> > +  v = r + k;   /* k has to live accross the call or all is probably lost  */
> > +  return 0;
> > +}
> > diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> > index e292a144967..6cf4a0e9f36 100644
> > --- a/gcc/tree-inline.c
> > +++ b/gcc/tree-inline.c
> > @@ -1529,7 +1529,21 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
> >    if (!is_gimple_debug (stmt)
> >        && id->param_body_adjs
> >        && id->param_body_adjs->m_dead_stmts.contains (stmt))
> > -    return NULL;
> > +    {
> > +      tree *dval = id->param_body_adjs->m_dead_stmt_debug_equiv.get (stmt);
> > +      if (!dval)
> > +	return NULL;
> > +
> > +      gcc_assert (is_gimple_assign (stmt));
> > +      tree lhs = gimple_assign_lhs (stmt);
> > +      tree *dvar = id->param_body_adjs->m_dead_ssa_debug_equiv.get (lhs);
> > +      gdebug *bind = gimple_build_debug_bind (*dvar, *dval, stmt);
> > +      if (id->reset_location)
> > +	gimple_set_location (bind, input_location);
> > +      id->debug_stmts.safe_push (bind);
> > +      gimple_seq_add_stmt (&stmts, bind);
> > +      return stmts;
> > +    }
> >  
> >    /* Begin by recognizing trees that we'll completely rewrite for the
> >       inlining context.  Our output for these trees is completely
> > @@ -1807,15 +1821,13 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
> >  
> >        if (gimple_debug_bind_p (stmt))
> >  	{
> > -	  tree value;
> > +	  tree var = gimple_debug_bind_get_var (stmt);
> > +	  tree value = gimple_debug_bind_get_value (stmt);
> >  	  if (id->param_body_adjs
> >  	      && id->param_body_adjs->m_dead_stmts.contains (stmt))
> > -	    value = NULL_TREE;
> > -	  else
> > -	    value = gimple_debug_bind_get_value (stmt);
> > -	  gdebug *copy
> > -	    = gimple_build_debug_bind (gimple_debug_bind_get_var (stmt),
> > -				       value, stmt);
> > +	    id->param_body_adjs->remap_with_debug_expressions (&value);
> > +
> > +	  gdebug *copy = gimple_build_debug_bind (var, value, stmt);
> >  	  if (id->reset_location)
> >  	    gimple_set_location (copy, input_location);
> >  	  id->debug_stmts.safe_push (copy);
> > @@ -6446,7 +6458,6 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >  	     in the debug info that var (whole DECL_ORIGIN is the parm
> >  	     PARM_DECL) is optimized away, but could be looked up at the
> >  	     call site as value of D#X there.  */
> > -	  tree vexpr;
> >  	  gimple_stmt_iterator cgsi
> >  	    = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
> >  	  gimple *def_temp;
> > @@ -6454,17 +6465,25 @@ tree_function_versioning (tree old_decl, tree new_decl,
> >  	  i = vec_safe_length (*debug_args);
> >  	  do
> >  	    {
> > +	      tree vexpr = NULL_TREE;
> >  	      i -= 2;
> >  	      while (var != NULL_TREE
> >  		     && DECL_ABSTRACT_ORIGIN (var) != (**debug_args)[i])
> >  		var = TREE_CHAIN (var);
> >  	      if (var == NULL_TREE)
> >  		break;
> > -	      vexpr = make_node (DEBUG_EXPR_DECL);
> >  	      tree parm = (**debug_args)[i];
> > -	      DECL_ARTIFICIAL (vexpr) = 1;
> > -	      TREE_TYPE (vexpr) = TREE_TYPE (parm);
> > -	      SET_DECL_MODE (vexpr, DECL_MODE (parm));
> > +	      if (tree parm_ddef = ssa_default_def (id.src_cfun, parm))
> > +		if (tree *d
> > +		    = param_body_adjs->m_dead_ssa_debug_equiv.get (parm_ddef))
> > +		  vexpr = *d;
> > +	      if (!vexpr)
> > +		{
> > +		  vexpr = make_node (DEBUG_EXPR_DECL);
> > +		  DECL_ARTIFICIAL (vexpr) = 1;
> > +		  TREE_TYPE (vexpr) = TREE_TYPE (parm);
> > +		  SET_DECL_MODE (vexpr, DECL_MODE (parm));
> > +		}
> >  	      def_temp = gimple_build_debug_bind (var, vexpr, NULL);
> >  	      gsi_insert_before (&cgsi, def_temp, GSI_NEW_STMT);
> >  	      def_temp = gimple_build_debug_source_bind (vexpr, parm, NULL);
> > -- 
> > 2.33.0
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)


More information about the Gcc-patches mailing list