langhooks-def.h (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, [...]): Remove.
authorRichard Henderson <rth@redhat.com>
Fri, 16 Jul 2004 20:51:31 +0000 (13:51 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 16 Jul 2004 20:51:31 +0000 (13:51 -0700)
        * 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
gcc/cp/ChangeLog
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/tree.c
gcc/langhooks-def.h
gcc/langhooks.c
gcc/langhooks.h
gcc/tree-inline.c

index 85b7b7ffc6461d102f86fc5c690f0a803428ba3d..054c04ab6cca3315df9eac441bddd9f89fa4aed6 100644 (file)
@@ -1,3 +1,17 @@
+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.
index f34b38ece3c8d4784edb2eb4559dca189ac97328..3945ebf0f53fd954d64f51c53f325c0e5b6392a2 100644 (file)
@@ -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.
index b6e933fede6f8b9ce75fd877d42fed3aafdb31b4..27c9270130f3c73e4f2ea42767d4117933f3d9c2 100644 (file)
@@ -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
index d8e83d6ee0e4a1fdd61854d4071780d8ae2d2bb7..f61dc39f24b8522c819f8b9568d15f02fd77f9a6 100644 (file)
@@ -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 */
index 75487214b79da9e03f3288cc86cb5f7d72253068..6279eb5d9b7401b2f5e4c3ecad73fe2697ef507a 100644 (file)
@@ -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;
        }
index 4321b8a1a725494370bcaeb1e4b05585f507bc97..253c1e6fea6da16b51f5878f10fbc719ce1ed0be 100644 (file)
@@ -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
index c57f34a327d3c23ba8e813f88d6e3337c21f4e50..ae8dcd2ef95f21c4e08c99866da9f22ddd8b42e1 100644 (file)
@@ -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, \
index c5a23f005f12a4fc6c8323a8abe0c042a59c1466..aa8dc3a633ac56d584014d24e1c04573bccba301 100644 (file)
@@ -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.  */
index 1669eb24a1045d69d2ed7b80c1f723ee54be82c4..345e89c5047e10f1f7fa0e24b1ae79840bf23b12 100644 (file)
@@ -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);
index 7387076d677f26b43df02456f1aaf1dd066ccc68..705216adb4f6e03b4063d1d57f45d588a798d1a8 100644 (file)
@@ -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);