From 7740f00d546112f3ceaa0c68caab28c10dc1d562 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 16 Jul 2004 13:51:31 -0700 Subject: 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 --- gcc/ChangeLog | 14 +++++ gcc/cp/ChangeLog | 6 ++ gcc/cp/cp-lang.c | 3 - gcc/cp/cp-tree.h | 2 - gcc/cp/decl.c | 4 +- gcc/cp/tree.c | 42 ------------- gcc/langhooks-def.h | 5 -- gcc/langhooks.c | 22 ------- gcc/langhooks.h | 2 - gcc/tree-inline.c | 169 ++++++++++++++++++++++++++++++---------------------- 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 + * 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 + * 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 + + * 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 * 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); -- cgit v1.1