/* Tree inlining hooks and declarations.
- Copyright 2001 Free Software Foundation, Inc.
+ Copyright 2001, 2003, 2004, 2005, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Contributed by Alexandre Oliva <aoliva@redhat.com>
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#ifndef GCC_TREE_INLINE_H
#define GCC_TREE_INLINE_H
+#include "pointer-set.h"
+
+struct cgraph_edge;
+
+/* Indicate the desired behavior wrt call graph edges. We can either
+ duplicate the edge (inlining, cloning), move the edge (versioning,
+ parallelization), or move the edges of the clones (saving). */
+
+enum copy_body_cge_which
+{
+ CB_CGE_DUPLICATE,
+ CB_CGE_MOVE,
+ CB_CGE_MOVE_CLONES
+};
+
+/* Data required for function body duplication. */
+
+typedef struct copy_body_data
+{
+ /* FUNCTION_DECL for function being inlined, or in general the
+ source function providing the original trees. */
+ tree src_fn;
+
+ /* FUNCTION_DECL for function being inlined into, or in general
+ the destination function receiving the new trees. */
+ tree dst_fn;
+
+ /* Callgraph node of the source function. */
+ struct cgraph_node *src_node;
+
+ /* Callgraph node of the destination function. */
+ struct cgraph_node *dst_node;
+
+ /* struct function for function being inlined. Usually this is the same
+ as DECL_STRUCT_FUNCTION (src_fn), but can be different if saved_cfg
+ and saved_eh are in use. */
+ struct function *src_cfun;
+
+ /* The VAR_DECL for the return value. */
+ tree retvar;
+
+ /* The map from local declarations in the inlined function to
+ equivalents in the function into which it is being inlined. */
+ struct pointer_map_t *decl_map;
+
+ /* Create a new decl to replace DECL in the destination function. */
+ tree (*copy_decl) (tree, struct copy_body_data *);
+
+ /* Current BLOCK. */
+ tree block;
+
+ /* GIMPLE_CALL if va arg parameter packs should be expanded or NULL
+ is not. */
+ gimple gimple_call;
+
+ /* Exception region the inlined call lie in. */
+ int eh_region;
+
+ /* Take region number in the function being copied, add this value and
+ get eh region number of the duplicate in the function we inline into. */
+ int eh_region_offset;
+
+ /* We use the same mechanism do all sorts of different things. Rather
+ than enumerating the different cases, we categorize the behavior
+ in the various situations. */
+
+ /* What to do with call graph edges. */
+ enum copy_body_cge_which transform_call_graph_edges;
+
+ /* True if a new CFG should be created. False for inlining, true for
+ everything else. */
+ bool transform_new_cfg;
+
+ /* True if RETURN_EXPRs should be transformed to just the contained
+ MODIFY_EXPR. The branch semantics of the return will be handled
+ by manipulating the CFG rather than a statement. */
+ bool transform_return_to_modify;
+
+ /* True if this statement will need to be regimplified. */
+ bool regimplify;
+
+ /* True if trees should not be unshared. */
+ bool do_not_unshare;
+
+ /* > 0 if we are remapping a type currently. */
+ int remapping_type_depth;
+
+ /* A function to be called when duplicating BLOCK nodes. */
+ void (*transform_lang_insert_block) (tree);
+
+ /* Statements that might be possibly folded. */
+ struct pointer_set_t *statements_to_fold;
+
+ /* Entry basic block to currently copied body. */
+ struct basic_block_def *entry_bb;
+} copy_body_data;
+
+/* Weights of constructions for estimate_num_insns. */
+
+typedef struct eni_weights_d
+{
+ /* Cost per call. */
+ unsigned call_cost;
+
+ /* Cost per call to a target specific builtin */
+ unsigned target_builtin_call_cost;
+
+ /* Cost of "expensive" div and mod operations. */
+ unsigned div_mod_cost;
+
+ /* Cost for omp construct. */
+ unsigned omp_cost;
+
+ /* True when time of statemnt should be estimated. Thus i.e
+ cost of switch statement is logarithmic rather than linear in number
+ of cases. */
+ bool time_based;
+} eni_weights;
+
+/* Weights that estimate_num_insns uses for heuristics in inlining. */
+
+extern eni_weights eni_inlining_weights;
+
+/* Weights that estimate_num_insns uses to estimate the size of the
+ produced code. */
+
+extern eni_weights eni_size_weights;
+
+/* Weights that estimate_num_insns uses to estimate the time necessary
+ to execute the produced code. */
+
+extern eni_weights eni_time_weights;
+
/* Function prototypes. */
-void optimize_inline_calls PARAMS ((tree));
-int tree_inlinable_function_p PARAMS ((tree));
-tree walk_tree PARAMS ((tree*, walk_tree_fn, void*, void*));
-tree walk_tree_without_duplicates PARAMS ((tree*, walk_tree_fn, void*));
-tree copy_tree_r PARAMS ((tree*, int*, void*));
-void clone_body PARAMS ((tree, tree, void*));
-void remap_save_expr PARAMS ((tree*, void*, tree, int*));
-
-/* LANG_WALK_SUBTREES is called by walk_tree() after handling common
- cases, but before walking code-specific sub-trees. If
- lang_walk_subtrees is defined for a language, it should handle
- language-specific tree codes, as well as language-specific
- information associated to common tree codes. If a tree node is
- completely handled within this function, it should set *SUBTREES to
- 0, so that generic handling isn't attempted. For language-specific
- tree codes, generic handling would abort(), so make sure it is set
- properly. Both SUBTREES and *SUBTREES is guaranteed to be non-zero
- when the function is called. */
-
-#define LANG_WALK_SUBTREES(TP,SUBTREES,FUNC,DATA,HTAB) \
- (lang_walk_subtrees \
- ? (*lang_walk_subtrees)((TP),(SUBTREES),(FUNC),(DATA),(HTAB)) \
- : 0)
-typedef tree treeopt_walk_subtrees_type PARAMS ((tree*, int*, walk_tree_fn,
- void*, void*));
-extern treeopt_walk_subtrees_type *lang_walk_subtrees;
-
-/* LANG_CANNOT_INLINE_TREE_FN is called to determine whether there are
- language-specific reasons for not inlining a given function. */
-
-#define LANG_CANNOT_INLINE_TREE_FN(FNP) \
- (lang_cannot_inline_tree_fn ? (*lang_cannot_inline_tree_fn)(FNP) : 0)
-typedef int treeopt_cannot_inline_tree_fn_type PARAMS ((tree*));
-extern treeopt_cannot_inline_tree_fn_type *lang_cannot_inline_tree_fn;
-
-/* LANG_DISREGARD_INLINE_LIMITS is called to determine whether a
- function should be inlined even if it would exceed inlining limits. */
-
-#define LANG_DISREGARD_INLINE_LIMITS(FN) \
- (lang_disregard_inline_limits ? (*lang_disregard_inline_limits)(FN) : 0)
-typedef int treeopt_disregard_inline_limits_type PARAMS ((tree));
-extern treeopt_disregard_inline_limits_type *lang_disregard_inline_limits;
-
-/* LANG_ADD_PENDING_FN_DECLS is called before starting to inline a
- function, to push any language-specific functions that should not
- be inlined into the current function, into VAFNP. PFN is the top
- of varray, and should be returned if no functions are pushed into
- VAFNP. The top of the varray should be returned. */
-
-#define LANG_ADD_PENDING_FN_DECLS(VAFNP,PFN) \
- (lang_add_pending_fn_decls \
- ? (*lang_add_pending_fn_decls)((VAFNP),(PFN)) \
- : (PFN))
-typedef tree treeopt_add_pending_fn_decls_type PARAMS ((void*,tree));
-extern treeopt_add_pending_fn_decls_type *lang_add_pending_fn_decls;
-
-/* LANG_TREE_CHAIN_MATTERS_P indicates whether the TREE_CHAIN of a
- language-specific tree node is relevant, i.e., whether it should be
- walked, copied and preserved across copies. */
-
-#define LANG_TREE_CHAIN_MATTERS_P(T) \
- (lang_tree_chain_matters_p ? (*lang_tree_chain_matters_p)(T) : 0)
-typedef int treeopt_tree_chain_matters_p_type PARAMS ((tree));
-extern treeopt_tree_chain_matters_p_type *lang_tree_chain_matters_p;
-
-/* LANG_AUTO_VAR_IN_FN_P is called to determine whether VT is an
- automatic variable defined in function FT. */
-
-#define LANG_AUTO_VAR_IN_FN_P(VT,FT) \
- (lang_auto_var_in_fn_p ? (*lang_auto_var_in_fn_p)((VT),(FT)) \
- : (DECL_P (VT) && DECL_CONTEXT (VT) == (FT) \
- && (((TREE_CODE (VT) == VAR_DECL || TREE_CODE (VT) == PARM_DECL) \
- && ! TREE_STATIC (VT)) \
- || TREE_CODE (VT) == LABEL_DECL \
- || TREE_CODE (VT) == RESULT_DECL)))
-typedef int treeopt_auto_var_in_fn_p_type PARAMS ((tree,tree));
-extern treeopt_auto_var_in_fn_p_type *lang_auto_var_in_fn_p;
-
-/* LANG_COPY_RES_DECL_FOR_INLINING should return a declaration for the
- result RES of function FN to be inlined into CALLER. NDP points to
- an integer that should be set in case a new declaration wasn't
- created (presumably because RES was of aggregate type, such that a
- TARGET_EXPR is used for the result). TEXPS is a pointer to a
- varray with the stack of TARGET_EXPRs seen while inlining functions
- into caller; the top of TEXPS is supposed to match RES. */
-
-#define LANG_COPY_RES_DECL_FOR_INLINING(RES,FN,CALLER,DM,NDP,TEXPS) \
- (lang_copy_res_decl_for_inlining \
- ? (*lang_copy_res_decl_for_inlining)((RES),(FN),(CALLER),\
- (DM),(NDP),(TEXPS)) \
- : copy_decl_for_inlining ((RES), (FN), (CALLER)))
-typedef tree treeopt_copy_res_decl_for_inlining_type PARAMS ((tree, tree,
- tree, void*,
- int*, void*));
-extern treeopt_copy_res_decl_for_inlining_type
-*lang_copy_res_decl_for_inlining;
-
-/* LANG_ANON_AGGR_TYPE_P determines whether T is a type node
- representing an anonymous aggregate (union, struct, etc), i.e., one
- whose members are in the same scope as the union itself. */
-
-#define LANG_ANON_AGGR_TYPE_P(T) \
- (lang_anon_aggr_type_p ? (*lang_anon_aggr_type_p)(T) : 0)
-typedef int treeopt_anon_aggr_type_p PARAMS ((tree));
-extern treeopt_anon_aggr_type_p *lang_anon_aggr_type_p;
-
-/* 0 if we should not perform inlining.
- 1 if we should expand functions calls inline at the tree level.
- 2 if we should consider *all* functions to be inline
- candidates. */
-
-extern int flag_inline_trees;
+extern tree copy_tree_body_r (tree *, int *, void *);
+extern void insert_decl_map (copy_body_data *, tree, tree);
+
+unsigned int optimize_inline_calls (tree);
+tree maybe_inline_call_in_expr (tree);
+bool tree_inlinable_function_p (tree);
+tree copy_tree_r (tree *, int *, void *);
+tree copy_decl_no_change (tree decl, copy_body_data *id);
+void save_body (tree, tree *, tree *);
+int estimate_move_cost (tree type);
+int estimate_num_insns (gimple, eni_weights *);
+int estimate_num_insns_fn (tree, eni_weights *);
+int count_insns_seq (gimple_seq, eni_weights *);
+bool tree_versionable_function_p (tree);
+bool tree_can_inline_p (struct cgraph_edge *e);
+
+extern gimple_seq remap_gimple_seq (gimple_seq, copy_body_data *);
+extern tree remap_decl (tree decl, copy_body_data *id);
+extern tree remap_type (tree type, copy_body_data *id);
+extern gimple_seq copy_gimple_seq_and_replace_locals (gimple_seq seq);
+
+extern HOST_WIDE_INT estimated_stack_frame_size (void);
#endif /* GCC_TREE_INLINE_H */