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.
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