On Mon, May 18, 2026 at 5:56 PM Andrew Pinski
<[email protected]> wrote:
>
> We use unshare_expr in many places now outside of gimple
> even. So it makes sense to move the decl to tree.h.
> A few sources can now even not need to include gimplify.h;
> I have not checked all of them just a few which seemed
> like including gimplify.h didn't make sense.
>
> This also moves the implementations of unshare_expr,
> unshare_expr_without_location and copy_if_shared from gimplify.cc
> to tree.cc to keep the headers "clean".
>
> Bootstrapped and tested on x86_64-linux-gnu.

OK

> Changes since v1:
>  * v2: Move implementation too.
>
> gcc/ChangeLog:
>
>         * cfgrtl.cc: Don't include gimplify.h or gimplify-me.h.
>         * cgraphbuild.cc: Likewise.
>         * emit-rtl.cc: Likewie.
>         * tree-ssa-dom.cc: Likewise.
>         * tree-ssa-dse.cc: Likewise.
>         * tree-ssa-loop-im.cc: Likewise.
>         * tree-ssa-loop-niter.cc: Likewise.
>         * tree-ssa-loop-unswitch.cc: Likewise.
>         * tree-ssa-math-opts.cc: Likewise.
>         * tree-ssa-phiopt.cc: Likewise.
>         * tree-ssa-phiprop.cc: Likewise.
>         * tree-ssa-pre.cc: Likewise.
>         * tree-ssa-propagate.cc: Likewise.
>         * tree-ssa-sccvn.cc: Likewise.
>         * gimplify.h (unshare_expr): Remove.
>         (unshare_expr_without_location): Remove.
>         (copy_if_shared): Remove.
>         * tree.h (unshare_expr): New decl.
>         (unshare_expr_without_location): Likewise.
>         (copy_if_shared): Likewise.
>         * gimplify.cc (mostly_copy_tree_r): Moved to tree.cc.
>         (copy_if_shared_r): Likewise.
>         (copy_if_shared): Likewise.
>         (unshare_expr): Likewise.
>         (prune_expr_location): Likewise.
>         (unshare_expr_without_location): Likewise.
>         * tree.cc (mostly_copy_tree_r): Moved from gimplify.cc
>         (copy_if_shared_r): Likewise.
>         (copy_if_shared): Likewise.
>         (unshare_expr): Likewise.
>         (prune_expr_location): Likewise.
>         (unshare_expr_without_location): Likewise.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
>  gcc/cfgrtl.cc                 |   1 -
>  gcc/cgraphbuild.cc            |   1 -
>  gcc/emit-rtl.cc               |   1 -
>  gcc/gimplify.cc               | 160 ----------------------------------
>  gcc/gimplify.h                |   3 -
>  gcc/tree-ssa-dom.cc           |   1 -
>  gcc/tree-ssa-dse.cc           |   1 -
>  gcc/tree-ssa-loop-im.cc       |   1 -
>  gcc/tree-ssa-loop-niter.cc    |   1 -
>  gcc/tree-ssa-loop-unswitch.cc |   1 -
>  gcc/tree-ssa-math-opts.cc     |   2 -
>  gcc/tree-ssa-phiopt.cc        |   2 -
>  gcc/tree-ssa-phiprop.cc       |   1 -
>  gcc/tree-ssa-pre.cc           |   1 -
>  gcc/tree-ssa-propagate.cc     |   1 -
>  gcc/tree-ssa-sccvn.cc         |   1 -
>  gcc/tree.cc                   | 159 +++++++++++++++++++++++++++++++++
>  gcc/tree.h                    |   9 ++
>  18 files changed, 168 insertions(+), 179 deletions(-)
>
> diff --git a/gcc/cfgrtl.cc b/gcc/cfgrtl.cc
> index 7714e5548c2..0ec72f08fa8 100644
> --- a/gcc/cfgrtl.cc
> +++ b/gcc/cfgrtl.cc
> @@ -62,7 +62,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-pass.h"
>  #include "print-rtl.h"
>  #include "rtl-iter.h"
> -#include "gimplify.h"
>  #include "profile.h"
>  #include "sreal.h"
>
> diff --git a/gcc/cgraphbuild.cc b/gcc/cgraphbuild.cc
> index e33a414310b..3faf8395db5 100644
> --- a/gcc/cgraphbuild.cc
> +++ b/gcc/cgraphbuild.cc
> @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "gimple-walk.h"
>  #include "ipa-utils.h"
>  #include "except.h"
> -#include "gimplify.h"
>
>  /* Context of record_reference.  */
>  struct record_reference_ctx
> diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
> index e41ec2283b8..7f5d267341a 100644
> --- a/gcc/emit-rtl.cc
> +++ b/gcc/emit-rtl.cc
> @@ -63,7 +63,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "rtx-vector-builder.h"
>  #include "gimple.h"
>  #include "gimple-ssa.h"
> -#include "gimplify.h"
>  #include "bbitmap.h"
>
>  struct target_rtl default_target_rtl;
> diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
> index e4db4b1d9bd..cdd039eb2bd 100644
> --- a/gcc/gimplify.cc
> +++ b/gcc/gimplify.cc
> @@ -896,131 +896,6 @@ gimple_add_tmp_var (tree tmp)
>      }
>  }
>
> -
> -
> -/* This page contains routines to unshare tree nodes, i.e. to duplicate tree
> -   nodes that are referenced more than once in GENERIC functions.  This is
> -   necessary because gimplification (translation into GIMPLE) is performed
> -   by modifying tree nodes in-place, so gimplification of a shared node in a
> -   first context could generate an invalid GIMPLE form in a second context.
> -
> -   This is achieved with a simple mark/copy/unmark algorithm that walks the
> -   GENERIC representation top-down, marks nodes with TREE_VISITED the first
> -   time it encounters them, duplicates them if they already have TREE_VISITED
> -   set, and finally removes the TREE_VISITED marks it has set.
> -
> -   The algorithm works only at the function level, i.e. it generates a 
> GENERIC
> -   representation of a function with no nodes shared within the function when
> -   passed a GENERIC function (except for nodes that are allowed to be 
> shared).
> -
> -   At the global level, it is also necessary to unshare tree nodes that are
> -   referenced in more than one function, for the same aforementioned reason.
> -   This requires some cooperation from the front-end.  There are 2 
> strategies:
> -
> -     1. Manual unsharing.  The front-end needs to call unshare_expr on every
> -        expression that might end up being shared across functions.
> -
> -     2. Deep unsharing.  This is an extension of regular unsharing.  Instead
> -        of calling unshare_expr on expressions that might be shared across
> -        functions, the front-end pre-marks them with TREE_VISITED.  This will
> -        ensure that they are unshared on the first reference within functions
> -        when the regular unsharing algorithm runs.  The counterpart is that
> -        this algorithm must look deeper than for manual unsharing, which is
> -        specified by LANG_HOOKS_DEEP_UNSHARING.
> -
> -  If there are only few specific cases of node sharing across functions, it 
> is
> -  probably easier for a front-end to unshare the expressions manually.  On 
> the
> -  contrary, if the expressions generated at the global level are as 
> widespread
> -  as expressions generated within functions, deep unsharing is very likely 
> the
> -  way to go.  */
> -
> -/* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
> -   These nodes model computations that must be done once.  If we were to
> -   unshare something like SAVE_EXPR(i++), the gimplification process would
> -   create wrong code.  However, if DATA is non-null, it must hold a pointer
> -   set that is used to unshare the subtrees of these nodes.  */
> -
> -static tree
> -mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
> -{
> -  tree t = *tp;
> -  enum tree_code code = TREE_CODE (t);
> -
> -  /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
> -     copy their subtrees if we can make sure to do it only once.  */
> -  if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
> -    {
> -      if (data && !((hash_set<tree> *)data)->add (t))
> -       ;
> -      else
> -       *walk_subtrees = 0;
> -    }
> -
> -  /* Stop at types, decls, constants like copy_tree_r.  */
> -  else if (TREE_CODE_CLASS (code) == tcc_type
> -          || TREE_CODE_CLASS (code) == tcc_declaration
> -          || TREE_CODE_CLASS (code) == tcc_constant)
> -    *walk_subtrees = 0;
> -
> -  /* Cope with the statement expression extension.  */
> -  else if (code == STATEMENT_LIST)
> -    ;
> -
> -  /* Leave the bulk of the work to copy_tree_r itself.  */
> -  else
> -    copy_tree_r (tp, walk_subtrees, NULL);
> -
> -  return NULL_TREE;
> -}
> -
> -/* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
> -   If *TP has been visited already, then *TP is deeply copied by calling
> -   mostly_copy_tree_r.  DATA is passed to mostly_copy_tree_r unmodified.  */
> -
> -static tree
> -copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
> -{
> -  tree t = *tp;
> -  enum tree_code code = TREE_CODE (t);
> -
> -  /* Skip types, decls, and constants.  But we do want to look at their
> -     types and the bounds of types.  Mark them as visited so we properly
> -     unmark their subtrees on the unmark pass.  If we've already seen them,
> -     don't look down further.  */
> -  if (TREE_CODE_CLASS (code) == tcc_type
> -      || TREE_CODE_CLASS (code) == tcc_declaration
> -      || TREE_CODE_CLASS (code) == tcc_constant)
> -    {
> -      if (TREE_VISITED (t))
> -       *walk_subtrees = 0;
> -      else
> -       TREE_VISITED (t) = 1;
> -    }
> -
> -  /* If this node has been visited already, unshare it and don't look
> -     any deeper.  */
> -  else if (TREE_VISITED (t))
> -    {
> -      walk_tree (tp, mostly_copy_tree_r, data, NULL);
> -      *walk_subtrees = 0;
> -    }
> -
> -  /* Otherwise, mark the node as visited and keep looking.  */
> -  else
> -    TREE_VISITED (t) = 1;
> -
> -  return NULL_TREE;
> -}
> -
> -/* Unshare most of the shared trees rooted at *TP.  DATA is passed to the
> -   copy_if_shared_r callback unmodified.  */
> -
> -void
> -copy_if_shared (tree *tp, void *data)
> -{
> -  walk_tree (tp, copy_if_shared_r, data, NULL);
> -}
> -
>  /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
>     any nested functions.  */
>
> @@ -1089,41 +964,6 @@ unvisit_body (tree fndecl)
>        unvisit_body (cgn->decl);
>  }
>
> -/* Unconditionally make an unshared copy of EXPR.  This is used when using
> -   stored expressions which span multiple functions, such as BINFO_VTABLE,
> -   as the normal unsharing process can't tell that they're shared.  */
> -
> -tree
> -unshare_expr (tree expr)
> -{
> -  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
> -  return expr;
> -}
> -
> -/* Worker for unshare_expr_without_location.  */
> -
> -static tree
> -prune_expr_location (tree *tp, int *walk_subtrees, void *)
> -{
> -  if (EXPR_P (*tp))
> -    SET_EXPR_LOCATION (*tp, UNKNOWN_LOCATION);
> -  else
> -    *walk_subtrees = 0;
> -  return NULL_TREE;
> -}
> -
> -/* Similar to unshare_expr but also prune all expression locations
> -   from EXPR.  */
> -
> -tree
> -unshare_expr_without_location (tree expr)
> -{
> -  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
> -  if (EXPR_P (expr))
> -    walk_tree (&expr, prune_expr_location, NULL, NULL);
> -  return expr;
> -}
> -
>  /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
>     one, OR_ELSE otherwise.  The location of a STATEMENT_LISTs
>     comprising at least one DEBUG_BEGIN_STMT followed by exactly one
> diff --git a/gcc/gimplify.h b/gcc/gimplify.h
> index caa35b426bd..18c7514c9a3 100644
> --- a/gcc/gimplify.h
> +++ b/gcc/gimplify.h
> @@ -62,9 +62,6 @@ extern tree get_initialized_tmp_var (tree, gimple_seq *, 
> gimple_seq * = NULL,
>  extern void declare_vars (tree, gimple *, bool);
>  extern void gimple_add_tmp_var (tree);
>  extern void gimple_add_tmp_var_fn (struct function *, tree);
> -extern void copy_if_shared (tree *, void * = NULL);
> -extern tree unshare_expr (tree);
> -extern tree unshare_expr_without_location (tree);
>  extern tree voidify_wrapper_expr (tree, tree);
>  extern tree build_and_jump (tree *);
>  extern enum gimplify_status gimplify_self_mod_expr (tree *, gimple_seq *,
> diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
> index 3be7979f528..37a29697319 100644
> --- a/gcc/tree-ssa-dom.cc
> +++ b/gcc/tree-ssa-dom.cc
> @@ -42,7 +42,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-ssa-scopedtables.h"
>  #include "tree-ssa-threadedge.h"
>  #include "tree-ssa-dom.h"
> -#include "gimplify.h"
>  #include "tree-cfgcleanup.h"
>  #include "dbgcnt.h"
>  #include "alloc-pool.h"
> diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc
> index 58cfa9ec129..2f97d6d1a1a 100644
> --- a/gcc/tree-ssa-dse.cc
> +++ b/gcc/tree-ssa-dse.cc
> @@ -37,7 +37,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-ssa-dse.h"
>  #include "builtins.h"
>  #include "gimple-fold.h"
> -#include "gimplify.h"
>  #include "tree-eh.h"
>  #include "cfganal.h"
>  #include "cgraph.h"
> diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
> index 4f7401e2d5d..2651e3919e3 100644
> --- a/gcc/tree-ssa-loop-im.cc
> +++ b/gcc/tree-ssa-loop-im.cc
> @@ -30,7 +30,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "fold-const.h"
>  #include "cfganal.h"
>  #include "tree-eh.h"
> -#include "gimplify.h"
>  #include "gimple-iterator.h"
>  #include "tree-cfg.h"
>  #include "tree-ssa-loop-manip.h"
> diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
> index c39401147ae..f179be1ffc7 100644
> --- a/gcc/tree-ssa-loop-niter.cc
> +++ b/gcc/tree-ssa-loop-niter.cc
> @@ -32,7 +32,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "fold-const.h"
>  #include "calls.h"
>  #include "intl.h"
> -#include "gimplify.h"
>  #include "gimple-iterator.h"
>  #include "tree-cfg.h"
>  #include "tree-ssa-loop-ivopts.h"
> diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
> index 96680bc64ea..a18c9ccfffa 100644
> --- a/gcc/tree-ssa-loop-unswitch.cc
> +++ b/gcc/tree-ssa-loop-unswitch.cc
> @@ -26,7 +26,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-pass.h"
>  #include "ssa.h"
>  #include "fold-const.h"
> -#include "gimplify.h"
>  #include "tree-cfg.h"
>  #include "tree-ssa.h"
>  #include "tree-ssa-loop-niter.h"
> diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
> index cd3fd2fc8fb..72f6dbd1a99 100644
> --- a/gcc/tree-ssa-math-opts.cc
> +++ b/gcc/tree-ssa-math-opts.cc
> @@ -102,8 +102,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "fold-const.h"
>  #include "gimple-iterator.h"
>  #include "gimple-fold.h"
> -#include "gimplify.h"
> -#include "gimplify-me.h"
>  #include "stor-layout.h"
>  #include "tree-cfg.h"
>  #include "tree-dfa.h"
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index e654e823636..18b5f284eee 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -35,9 +35,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "fold-const.h"
>  #include "stor-layout.h"
>  #include "cfganal.h"
> -#include "gimplify.h"
>  #include "gimple-iterator.h"
> -#include "gimplify-me.h"
>  #include "tree-cfg.h"
>  #include "tree-dfa.h"
>  #include "domwalk.h"
> diff --git a/gcc/tree-ssa-phiprop.cc b/gcc/tree-ssa-phiprop.cc
> index 54f3ad8d9f8..7e7a4534eb2 100644
> --- a/gcc/tree-ssa-phiprop.cc
> +++ b/gcc/tree-ssa-phiprop.cc
> @@ -29,7 +29,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "gimple-pretty-print.h"
>  #include "fold-const.h"
>  #include "tree-eh.h"
> -#include "gimplify.h"
>  #include "gimple-iterator.h"
>  #include "stor-layout.h"
>  #include "tree-ssa-loop.h"
> diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
> index 0e5eaf86bc7..5ded68443dd 100644
> --- a/gcc/tree-ssa-pre.cc
> +++ b/gcc/tree-ssa-pre.cc
> @@ -37,7 +37,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "gimple-iterator.h"
>  #include "gimple-fold.h"
>  #include "tree-eh.h"
> -#include "gimplify.h"
>  #include "tree-cfg.h"
>  #include "tree-into-ssa.h"
>  #include "tree-dfa.h"
> diff --git a/gcc/tree-ssa-propagate.cc b/gcc/tree-ssa-propagate.cc
> index a87c45d3a12..992b4243670 100644
> --- a/gcc/tree-ssa-propagate.cc
> +++ b/gcc/tree-ssa-propagate.cc
> @@ -30,7 +30,6 @@
>  #include "gimple-iterator.h"
>  #include "gimple-fold.h"
>  #include "tree-eh.h"
> -#include "gimplify.h"
>  #include "tree-cfg.h"
>  #include "tree-ssa.h"
>  #include "tree-ssa-propagate.h"
> diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
> index e19beb439d2..79b6b465294 100644
> --- a/gcc/tree-ssa-sccvn.cc
> +++ b/gcc/tree-ssa-sccvn.cc
> @@ -42,7 +42,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "gimple-iterator.h"
>  #include "gimple-fold.h"
>  #include "tree-eh.h"
> -#include "gimplify.h"
>  #include "flags.h"
>  #include "dojump.h"
>  #include "explow.h"
> diff --git a/gcc/tree.cc b/gcc/tree.cc
> index 8479ffab584..e3df004be97 100644
> --- a/gcc/tree.cc
> +++ b/gcc/tree.cc
> @@ -15847,6 +15847,165 @@ diagnose_versioned_decls (tree old_decl, tree 
> new_decl)
>             (old_target_attr, old_decl, new_target_attr, new_decl);
>  }
>
> +
> +/* This page contains routines to unshare tree nodes, i.e. to duplicate tree
> +   nodes that are referenced more than once in GENERIC functions.  This is
> +   necessary because gimplification (translation into GIMPLE) is performed
> +   by modifying tree nodes in-place, so gimplification of a shared node in a
> +   first context could generate an invalid GIMPLE form in a second context.
> +
> +   This is achieved with a simple mark/copy/unmark algorithm that walks the
> +   GENERIC representation top-down, marks nodes with TREE_VISITED the first
> +   time it encounters them, duplicates them if they already have TREE_VISITED
> +   set, and finally removes the TREE_VISITED marks it has set.
> +
> +   The algorithm works only at the function level, i.e. it generates a 
> GENERIC
> +   representation of a function with no nodes shared within the function when
> +   passed a GENERIC function (except for nodes that are allowed to be 
> shared).
> +
> +   At the global level, it is also necessary to unshare tree nodes that are
> +   referenced in more than one function, for the same aforementioned reason.
> +   This requires some cooperation from the front-end.  There are 2 
> strategies:
> +
> +     1. Manual unsharing.  The front-end needs to call unshare_expr on every
> +        expression that might end up being shared across functions.
> +
> +     2. Deep unsharing.  This is an extension of regular unsharing.  Instead
> +        of calling unshare_expr on expressions that might be shared across
> +        functions, the front-end pre-marks them with TREE_VISITED.  This will
> +        ensure that they are unshared on the first reference within functions
> +        when the regular unsharing algorithm runs.  The counterpart is that
> +        this algorithm must look deeper than for manual unsharing, which is
> +        specified by LANG_HOOKS_DEEP_UNSHARING.
> +
> +  If there are only few specific cases of node sharing across functions, it 
> is
> +  probably easier for a front-end to unshare the expressions manually.  On 
> the
> +  contrary, if the expressions generated at the global level are as 
> widespread
> +  as expressions generated within functions, deep unsharing is very likely 
> the
> +  way to go.  */
> +
> +/* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
> +   These nodes model computations that must be done once.  If we were to
> +   unshare something like SAVE_EXPR(i++), the gimplification process would
> +   create wrong code.  However, if DATA is non-null, it must hold a pointer
> +   set that is used to unshare the subtrees of these nodes.  */
> +
> +static tree
> +mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
> +{
> +  tree t = *tp;
> +  enum tree_code code = TREE_CODE (t);
> +
> +  /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
> +     copy their subtrees if we can make sure to do it only once.  */
> +  if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
> +    {
> +      if (data && !((hash_set<tree> *)data)->add (t))
> +       ;
> +      else
> +       *walk_subtrees = 0;
> +    }
> +
> +  /* Stop at types, decls, constants like copy_tree_r.  */
> +  else if (TREE_CODE_CLASS (code) == tcc_type
> +          || TREE_CODE_CLASS (code) == tcc_declaration
> +          || TREE_CODE_CLASS (code) == tcc_constant)
> +    *walk_subtrees = 0;
> +
> +  /* Cope with the statement expression extension.  */
> +  else if (code == STATEMENT_LIST)
> +    ;
> +
> +  /* Leave the bulk of the work to copy_tree_r itself.  */
> +  else
> +    copy_tree_r (tp, walk_subtrees, NULL);
> +
> +  return NULL_TREE;
> +}
> +
> +/* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
> +   If *TP has been visited already, then *TP is deeply copied by calling
> +   mostly_copy_tree_r.  DATA is passed to mostly_copy_tree_r unmodified.  */
> +
> +static tree
> +copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
> +{
> +  tree t = *tp;
> +  enum tree_code code = TREE_CODE (t);
> +
> +  /* Skip types, decls, and constants.  But we do want to look at their
> +     types and the bounds of types.  Mark them as visited so we properly
> +     unmark their subtrees on the unmark pass.  If we've already seen them,
> +     don't look down further.  */
> +  if (TREE_CODE_CLASS (code) == tcc_type
> +      || TREE_CODE_CLASS (code) == tcc_declaration
> +      || TREE_CODE_CLASS (code) == tcc_constant)
> +    {
> +      if (TREE_VISITED (t))
> +       *walk_subtrees = 0;
> +      else
> +       TREE_VISITED (t) = 1;
> +    }
> +
> +  /* If this node has been visited already, unshare it and don't look
> +     any deeper.  */
> +  else if (TREE_VISITED (t))
> +    {
> +      walk_tree (tp, mostly_copy_tree_r, data, NULL);
> +      *walk_subtrees = 0;
> +    }
> +
> +  /* Otherwise, mark the node as visited and keep looking.  */
> +  else
> +    TREE_VISITED (t) = 1;
> +
> +  return NULL_TREE;
> +}
> +
> +/* Unshare most of the shared trees rooted at *TP.  DATA is passed to the
> +   copy_if_shared_r callback unmodified.  */
> +
> +void
> +copy_if_shared (tree *tp, void *data)
> +{
> +  walk_tree (tp, copy_if_shared_r, data, NULL);
> +}
> +
> +/* Unconditionally make an unshared copy of EXPR.  This is used when using
> +   stored expressions which span multiple functions, such as BINFO_VTABLE,
> +   as the normal unsharing process can't tell that they're shared.  */
> +
> +tree
> +unshare_expr (tree expr)
> +{
> +  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
> +  return expr;
> +}
> +
> +/* Worker for unshare_expr_without_location.  */
> +
> +static tree
> +prune_expr_location (tree *tp, int *walk_subtrees, void *)
> +{
> +  if (EXPR_P (*tp))
> +    SET_EXPR_LOCATION (*tp, UNKNOWN_LOCATION);
> +  else
> +    *walk_subtrees = 0;
> +  return NULL_TREE;
> +}
> +
> +/* Similar to unshare_expr but also prune all expression locations
> +   from EXPR.  */
> +
> +tree
> +unshare_expr_without_location (tree expr)
> +{
> +  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
> +  if (EXPR_P (expr))
> +    walk_tree (&expr, prune_expr_location, NULL, NULL);
> +  return expr;
> +}
> +
>  void
>  tree_cc_finalize (void)
>  {
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 3b012d0fd6a..05400ada20b 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -7204,4 +7204,13 @@ extern bool disjoint_version_decls (tree, tree);
>  /* Checks if two overlapping decls are not mergeable.  */
>  extern bool diagnose_versioned_decls (tree, tree);
>
> +/* Unshare tree if needed.  */
> +extern tree unshare_expr (tree);
> +
> +/* Unshare tree if needed.
> +   Removing the locations if an expr.  */
> +extern tree unshare_expr_without_location (tree);
> +
> +extern void copy_if_shared (tree *, void * = NULL);
> +
>  #endif  /* GCC_TREE_H  */
> --
> 2.43.0
>

Reply via email to