aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-07-16 13:51:31 -0700
committerRichard Henderson <rth@gcc.gnu.org>2004-07-16 13:51:31 -0700
commit7740f00d546112f3ceaa0c68caab28c10dc1d562 (patch)
tree1fb4722f84cb260ae7dddc523251e0014eb13091
parent26e79d1018d0e6bd50b96f5f3fabb0376e392dff (diff)
downloadgcc-7740f00d546112f3ceaa0c68caab28c10dc1d562.zip
gcc-7740f00d546112f3ceaa0c68caab28c10dc1d562.tar.gz
gcc-7740f00d546112f3ceaa0c68caab28c10dc1d562.tar.bz2
langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, [...]): Remove.
* langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, lhd_tree_inlining_copy_res_decl_for_inlining): Remove. * langhooks.c (lhd_tree_inlining_copy_res_decl_for_inlining): Remove. * langhooks.h (struct lang_hooks_for_tree_inlining): Remove copy_res_decl_for_inlining. * tree-inline.c (declare_return_variable): New modify_dest argument. Use it as the return value, when possible or manditory. Handle TREE_ADDRESSABLE types. (expand_call_inline): Extract MODIFY_EXPR lhs for call. Simplify replacement of CALL_EXPR. cp/ * cp-lang.c (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING): Die. * cp-tree.h (cp_copy_res_decl_for_inlining): Remove. * tree.c (cp_copy_res_decl_for_inlining): Remove. From-SVN: r84831
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-lang.c3
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/tree.c42
-rw-r--r--gcc/langhooks-def.h5
-rw-r--r--gcc/langhooks.c22
-rw-r--r--gcc/langhooks.h2
-rw-r--r--gcc/tree-inline.c169
10 files changed, 120 insertions, 149 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85b7b7f..054c04a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,19 @@
2004-07-16 Richard Henderson <rth@redhat.com>
+ * langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING,
+ lhd_tree_inlining_copy_res_decl_for_inlining): Remove.
+ * langhooks.c (lhd_tree_inlining_copy_res_decl_for_inlining): Remove.
+ * langhooks.h (struct lang_hooks_for_tree_inlining): Remove
+ copy_res_decl_for_inlining.
+
+ * tree-inline.c (declare_return_variable): New modify_dest argument.
+ Use it as the return value, when possible or manditory. Handle
+ TREE_ADDRESSABLE types.
+ (expand_call_inline): Extract MODIFY_EXPR lhs for call. Simplify
+ replacement of CALL_EXPR.
+
+2004-07-16 Richard Henderson <rth@redhat.com>
+
* tree-flow.h (struct var_ann_d): Remove has_hidden_use.
* gimple-low.c (expand_var_p): Don't check it.
* tree-ssa-alias.c (setup_pointers_and_addressables): Likewise.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f34b38e..3945ebf 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2004-07-16 Richard Henderson <rth@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING): Die.
+ * cp-tree.h (cp_copy_res_decl_for_inlining): Remove.
+ * tree.c (cp_copy_res_decl_for_inlining): Remove.
+
2004-07-16 Nathan Sidwell <nathan@codesourcery.com>
* class.c (finish_struct_bits): Use for loop.
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index b6e933f..27c9270 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -131,9 +131,6 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#undef LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P
#define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \
cp_auto_var_in_fn_p
-#undef LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING
-#define LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING \
- cp_copy_res_decl_for_inlining
#undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d8e83d6..f61dc39 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4206,8 +4206,6 @@ extern int cp_cannot_inline_tree_fn (tree*);
extern tree cp_add_pending_fn_decls (void*,tree);
extern int cp_is_overload_p (tree);
extern int cp_auto_var_in_fn_p (tree,tree);
-extern tree cp_copy_res_decl_for_inlining (tree, tree, tree, void*,
- int*, tree);
extern void cp_update_decl_after_saving (tree, void *);
/* in typeck.c */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7548721..6279eb5 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10680,8 +10680,8 @@ cxx_push_function_context (struct function * f)
*cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
/* We don't need the saved data anymore. Unless this is an inline
- function; we need the named return value info for
- cp_copy_res_decl_for_inlining. */
+ function; we need the named return value info for
+ declare_return_variable. */
if (! DECL_INLINE (fn))
DECL_SAVED_FUNCTION_DATA (fn) = NULL;
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 4321b8a..253c1e6 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2093,48 +2093,6 @@ cp_auto_var_in_fn_p (tree var, tree fn)
&& nonstatic_local_decl_p (var));
}
-/* Tell whether a declaration is needed for the RESULT of a function
- FN being inlined into CALLER or if the top node of target_exprs is
- to be used. */
-
-tree
-cp_copy_res_decl_for_inlining (tree result,
- tree fn,
- tree caller,
- void* decl_map_ ATTRIBUTE_UNUSED,
- int* need_decl,
- tree return_slot_addr)
-{
- tree var;
-
- /* If FN returns an aggregate then the caller will always pass the
- address of the return slot explicitly. If we were just to
- create a new VAR_DECL here, then the result of this function
- would be copied (bitwise) into the variable initialized by the
- TARGET_EXPR. That's incorrect, so we must transform any
- references to the RESULT into references to the target. */
-
- /* We should have an explicit return slot iff the return type is
- TREE_ADDRESSABLE. See gimplify_aggr_init_expr. */
- if (TREE_ADDRESSABLE (TREE_TYPE (result))
- != (return_slot_addr != NULL_TREE))
- abort ();
-
- *need_decl = !return_slot_addr;
- if (return_slot_addr)
- {
- var = build_indirect_ref (return_slot_addr, "");
- if (! same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (var),
- TREE_TYPE (result)))
- abort ();
- }
- /* Otherwise, make an appropriate copy. */
- else
- var = copy_decl_for_inlining (result, fn, caller);
-
- return var;
-}
-
/* FN body has been duplicated. Update language specific fields. */
void
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index c57f34a..ae8dcd2 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -78,8 +78,6 @@ extern int lhd_tree_inlining_cannot_inline_tree_fn (tree *);
extern int lhd_tree_inlining_disregard_inline_limits (tree);
extern tree lhd_tree_inlining_add_pending_fn_decls (void *, tree);
extern int lhd_tree_inlining_auto_var_in_fn_p (tree, tree);
-extern tree lhd_tree_inlining_copy_res_decl_for_inlining (tree, tree, tree,
- void *, int *, tree);
extern int lhd_tree_inlining_anon_aggr_type_p (tree);
extern int lhd_tree_inlining_start_inlining (tree);
extern void lhd_tree_inlining_end_inlining (tree);
@@ -150,8 +148,6 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
lhd_tree_inlining_add_pending_fn_decls
#define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \
lhd_tree_inlining_auto_var_in_fn_p
-#define LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING \
- lhd_tree_inlining_copy_res_decl_for_inlining
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
lhd_tree_inlining_anon_aggr_type_p
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
@@ -169,7 +165,6 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS, \
LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS, \
LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
- LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P, \
LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, \
LANG_HOOKS_TREE_INLINING_START_INLINING, \
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index c5a23f0..aa8dc3a 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -362,28 +362,6 @@ lhd_tree_inlining_auto_var_in_fn_p (tree var, tree fn)
|| TREE_CODE (var) == RESULT_DECL));
}
-/* lang_hooks.tree_inlining.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. */
-
-tree
-lhd_tree_inlining_copy_res_decl_for_inlining (tree res, tree fn, tree caller,
- void *dm ATTRIBUTE_UNUSED,
- int *ndp ATTRIBUTE_UNUSED,
- tree return_slot_addr ATTRIBUTE_UNUSED)
-{
- if (return_slot_addr)
- return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (return_slot_addr)),
- return_slot_addr);
- else
- return copy_decl_for_inlining (res, fn, caller);
-}
-
/* lang_hooks.tree_inlining.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. */
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 1669eb2..345e89c5 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -40,8 +40,6 @@ struct lang_hooks_for_tree_inlining
int (*disregard_inline_limits) (tree);
tree (*add_pending_fn_decls) (void *, tree);
int (*auto_var_in_fn_p) (tree, tree);
- tree (*copy_res_decl_for_inlining) (tree, tree, tree,
- void *, int *, tree);
int (*anon_aggr_type_p) (tree);
bool (*var_mod_type_p) (tree, tree);
int (*start_inlining) (tree);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 7387076..705216a 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -122,7 +122,6 @@ typedef struct inline_data
decisions about when a function is too big to inline. */
#define INSNS_PER_STMT (10)
-static tree declare_return_variable (inline_data *, tree, tree *);
static tree copy_body_r (tree *, int *, void *);
static tree copy_body (inline_data *);
static tree expand_call_inline (tree *, int *, void *);
@@ -851,35 +850,102 @@ initialize_inlined_parameters (inline_data *id, tree args, tree static_chain,
return init_stmts;
}
-/* Declare a return variable to replace the RESULT_DECL for the
- function we are calling. An appropriate decl is returned.
-
- ??? Needs documentation of parameters. */
+/* Declare a return variable to replace the RESULT_DECL for the function we
+ are calling. RETURN_SLOT_ADDR, if non-null, was a fake parameter that
+ took the address of the result. MODIFY_DEST, if non-null, was the LHS of
+ the MODIFY_EXPR to which this call is the RHS.
+
+ The return value is a (possibly null) value that is the result of the
+ function as seen by the callee. *USE_P is a (possibly null) value that
+ holds the result as seen by the caller. */
static tree
-declare_return_variable (inline_data *id, tree return_slot_addr, tree *use_p)
+declare_return_variable (inline_data *id, tree return_slot_addr,
+ tree modify_dest, tree *use_p)
{
- tree fn = VARRAY_TOP_TREE (id->fns);
- tree result = DECL_RESULT (fn);
- int need_return_decl = 1;
- tree var;
+ tree callee = VARRAY_TOP_TREE (id->fns);
+ tree caller = VARRAY_TREE (id->fns, 0);
+ tree result = DECL_RESULT (callee);
+ tree callee_type = TREE_TYPE (result);
+ tree caller_type = TREE_TYPE (TREE_TYPE (callee));
+ tree var, use;
/* We don't need to do anything for functions that don't return
anything. */
- if (!result || VOID_TYPE_P (TREE_TYPE (result)))
+ if (!result || VOID_TYPE_P (callee_type))
{
*use_p = NULL_TREE;
return NULL_TREE;
}
- var = (lang_hooks.tree_inlining.copy_res_decl_for_inlining
- (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
- &need_return_decl, return_slot_addr));
-
+ /* If there was a return slot, then the return value the the
+ dereferenced address of that object. */
+ if (return_slot_addr)
+ {
+ /* The front end shouldn't have used both return_slot_addr and
+ a modify expression. */
+ if (modify_dest)
+ abort ();
+ var = build_fold_indirect_ref (return_slot_addr);
+ use = NULL;
+ goto done;
+ }
+
+ /* All types requiring non-trivial constructors should have been handled. */
+ if (TREE_ADDRESSABLE (callee_type))
+ abort ();
+
+ /* Attempt to avoid creating a new temporary variable. */
+ if (modify_dest)
+ {
+ bool use_it = false;
+
+ /* We can't use MODIFY_DEST if there's type promotion involved. */
+ if (!lang_hooks.types_compatible_p (caller_type, callee_type))
+ use_it = false;
+
+ /* ??? If we're assigning to a variable sized type, then we must
+ reuse the destination variable, because we've no good way to
+ create variable sized temporaries at this point. */
+ else if (TREE_CODE (TYPE_SIZE_UNIT (caller_type)) != INTEGER_CST)
+ use_it = true;
+
+ /* If the callee cannot possibly modify MODIFY_DEST, then we can
+ reuse it as the result of the call directly. Don't do this if
+ it would promote MODIFY_DEST to addressable. */
+ else if (!TREE_STATIC (modify_dest)
+ && !TREE_ADDRESSABLE (modify_dest)
+ && !TREE_ADDRESSABLE (result))
+ use_it = true;
+
+ if (use_it)
+ {
+ var = modify_dest;
+ use = NULL;
+ goto done;
+ }
+ }
+
+ if (TREE_CODE (TYPE_SIZE_UNIT (callee_type)) != INTEGER_CST)
+ abort ();
+
+ var = copy_decl_for_inlining (result, callee, caller);
+ DECL_SEEN_IN_BIND_EXPR_P (var) = 1;
+ DECL_STRUCT_FUNCTION (caller)->unexpanded_var_list
+ = tree_cons (NULL_TREE, var,
+ DECL_STRUCT_FUNCTION (caller)->unexpanded_var_list);
+
/* Do not have the rest of GCC warn about this variable as it should
not be visible to the user. */
TREE_NO_WARNING (var) = 1;
+ /* Build the use expr. If the return type of the function was
+ promoted, convert it back to the expected type. */
+ use = var;
+ if (!lang_hooks.types_compatible_p (TREE_TYPE (var), caller_type))
+ use = fold_convert (caller_type, var);
+
+ done:
/* Register the VAR_DECL as the equivalent for the RESULT_DECL; that
way, when the RESULT_DECL is encountered, it will be
automatically replaced by the VAR_DECL. */
@@ -888,30 +954,8 @@ declare_return_variable (inline_data *id, tree return_slot_addr, tree *use_p)
/* Remember this so we can ignore it in remap_decls. */
id->retvar = var;
- /* Build the use expr. If the return type of the function was
- promoted, convert it back to the expected type. */
- if (return_slot_addr)
- /* The function returns through an explicit return slot, not a normal
- return value. */
- *use_p = NULL_TREE;
- else if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn)))
- *use_p = var;
- else if (TREE_CODE (var) == INDIRECT_REF)
- *use_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (fn)),
- TREE_OPERAND (var, 0));
- else if (TREE_ADDRESSABLE (TREE_TYPE (var)))
- abort ();
- else
- *use_p = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), var);
-
- /* Build the declaration statement if FN does not return an
- aggregate. */
- if (need_return_decl)
- return var;
- /* If FN does return an aggregate, there's no need to declare the
- return variable; we're using a variable in our caller's frame. */
- else
- return NULL_TREE;
+ *use_p = use;
+ return var;
}
/* Returns nonzero if a function can be inlined as a tree. */
@@ -1385,10 +1429,10 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
tree fn;
tree arg_inits;
tree *inlined_body;
- tree inline_result;
splay_tree st;
tree args;
tree return_slot_addr;
+ tree modify_dest;
location_t saved_location;
struct cgraph_edge *edge;
const char *reason;
@@ -1517,7 +1561,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
statements within the function to jump to. The type of the
statement expression is the return type of the function call. */
stmt = NULL;
- expr = build (BIND_EXPR, TREE_TYPE (TREE_TYPE (fn)), NULL_TREE,
+ expr = build (BIND_EXPR, void_type_node, NULL_TREE,
stmt, make_node (BLOCK));
BLOCK_ABSTRACT_ORIGIN (BIND_EXPR_BLOCK (expr)) = fn;
@@ -1586,10 +1630,16 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
|| TREE_CODE (DECL_INITIAL (fn)) != BLOCK)
abort ();
+ /* Find the lhs to which the result of this call is assigned. */
+ modify_dest = tsi_stmt (id->tsi);
+ if (TREE_CODE (modify_dest) == MODIFY_EXPR)
+ modify_dest = TREE_OPERAND (modify_dest, 0);
+ else
+ modify_dest = NULL;
+
/* Declare the return variable for the function. */
- decl = declare_return_variable (id, return_slot_addr, &use_retvar);
- if (decl)
- declare_inline_vars (expr, decl);
+ decl = declare_return_variable (id, return_slot_addr,
+ modify_dest, &use_retvar);
/* After we've initialized the parameters, we insert the body of the
function itself. */
@@ -1611,12 +1661,6 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
append_to_statement_list (label, &BIND_EXPR_BODY (expr));
}
- /* Finally, mention the returned value so that the value of the
- statement-expression is the returned value of the function. */
- if (use_retvar)
- /* Set TREE_TYPE on BIND_EXPR? */
- append_to_statement_list_force (use_retvar, &BIND_EXPR_BODY (expr));
-
/* Clean up. */
splay_tree_delete (id->decl_map);
id->decl_map = st;
@@ -1624,28 +1668,16 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
/* The new expression has side-effects if the old one did. */
TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (t);
- /* We want to create a new variable to hold the result of the inlined
- body. This new variable needs to be added to the function which we
- are inlining into, thus the saving and restoring of
- current_function_decl. */
- {
- tree save_decl = current_function_decl;
- current_function_decl = id->node->decl;
- inline_result = voidify_wrapper_expr (expr, NULL);
- current_function_decl = save_decl;
- }
+ tsi_link_before (&id->tsi, expr, TSI_SAME_STMT);
/* If the inlined function returns a result that we care about,
then we're going to need to splice in a MODIFY_EXPR. Otherwise
the call was a standalone statement and we can just replace it
with the BIND_EXPR inline representation of the called function. */
- if (TREE_CODE (tsi_stmt (id->tsi)) != CALL_EXPR)
- {
- tsi_link_before (&id->tsi, expr, TSI_SAME_STMT);
- *tp = inline_result;
- }
+ if (!use_retvar || !modify_dest)
+ *tsi_stmt_ptr (id->tsi) = build_empty_stmt ();
else
- *tp = expr;
+ *tp = use_retvar;
/* When we gimplify a function call, we may clear TREE_SIDE_EFFECTS on
the call if it is to a "const" function. Thus the copy of
@@ -1660,11 +1692,6 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
the toplevel expression. */
recalculate_side_effects (expr);
- /* If the value of the new expression is ignored, that's OK. We
- don't warn about this for CALL_EXPRs, so we shouldn't warn about
- the equivalent inlined version either. */
- TREE_USED (*tp) = 1;
-
/* Update callgraph if needed. */
cgraph_remove_node (edge->callee);