decl.c (init_decl_processing): Reenable inlining on trees.
authorMark Mitchell <mark@codesourcery.com>
Thu, 9 Dec 1999 19:13:33 +0000 (19:13 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 9 Dec 1999 19:13:33 +0000 (19:13 +0000)
* decl.c (init_decl_processing): Reenable inlining on trees.
(finish_function): Likewise.
* expr.c (cplus_expand_expr): Don't handle AGGR_INIT_EXPR here.
* semantics.c (simplify_aggr_init_exprs): New function.
(expand_body): Use it.
* tree.c (walk_tree): Special-case TARGET_EXPRs since they
sometimes present the same sub-tree twice.

From-SVN: r30849

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/expr.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/g++.old-deja/g++.other/inline1.C [new file with mode: 0644]

index 072823f5783fbda8363a4ed3746be01d35ba3cff..b6505e55d75d1a1b44cabb84a18d7ff2c85155ff 100644 (file)
@@ -1,5 +1,13 @@
 1999-12-09  Mark Mitchell  <mark@codesourcery.com>
 
+       * decl.c (init_decl_processing): Reenable inlining on trees.
+       (finish_function): Likewise.
+       * expr.c (cplus_expand_expr): Don't handle AGGR_INIT_EXPR here.
+       * semantics.c (simplify_aggr_init_exprs): New function.
+       (expand_body): Use it.
+       * tree.c (walk_tree): Special-case TARGET_EXPRs since they
+       sometimes present the same sub-tree twice.
+       
        * dump.c (dequeue_and_dump): Abbreviate `class' as `cls', not
        `csl'.
 
index 8e233f6a966925be3939ec4cb1d4008d287d9167..b6a62ea48348bb396e93378bb3218f562fee502a 100644 (file)
@@ -5973,10 +5973,8 @@ init_decl_processing ()
     flag_strict_prototype = pedantic;
   if (! flag_permissive && ! pedantic)
     flag_pedantic_errors = 1;
-#if 0
   if (!flag_no_inline)
     flag_inline_trees = 1;
-#endif
 
   strict_prototypes_lang_c = flag_strict_prototype;
 
@@ -13669,7 +13667,6 @@ finish_function (lineno, flags)
   if (!expanding_p && !processing_template_decl)
     save_function_data (fndecl);
 
-#if 0
   /* If this function calls `setjmp' it cannot be inlined.  When
      `longjmp' is called it is not guaranteed to restore the value of
      local variables that have been modified since the call to
@@ -13681,7 +13678,6 @@ finish_function (lineno, flags)
      function.)  */
   if (!expanding_p && !processing_template_decl && calls_setjmp_p (fndecl))
     DECL_UNINLINABLE (fndecl) = 1;
-#endif
 
   if (expand_p)
     {
index 094ba501cd7841bc3224b57080964805d9eb03a1..2ac29f9f2c6379b054df46eee2337df5c528678e 100644 (file)
@@ -120,102 +120,6 @@ cplus_expand_expr (exp, target, tmode, modifier)
 
   switch (code)
     {
-    case AGGR_INIT_EXPR:
-      {
-       /* Something needs to be initialized, but we didn't know
-          where that thing was when building the tree.  For example,
-          it could be the return value of a function, or a parameter
-          to a function which lays down in the stack, or a temporary
-          variable which must be passed by reference.
-
-          Cleanups are handled in a language-specific way: they
-          might be run by the called function (true in GNU C++
-          for parameters with cleanups), or they might be
-          run by the caller, after the call (true in GNU C++
-          for other cleanup needs).  */
-
-       tree func = TREE_OPERAND (exp, 0);
-       tree args = TREE_OPERAND (exp, 1);
-       tree type = TREE_TYPE (exp), slot;
-       tree call_exp;
-       rtx call_target, return_target;
-       int pcc_struct_return = 0;
-
-       /* The expression `init' wants to initialize what
-          `target' represents.  SLOT holds the slot for TARGET.  */
-       slot = TREE_OPERAND (exp, 2);
-
-       /* Should always be called with a target.  */
-       my_friendly_assert (target != NULL_RTX, 205);
-
-       /* The target the initializer will initialize (CALL_TARGET)
-          must now be directed to initialize the target we are
-          supposed to initialize (TARGET).  The semantics for
-          choosing what CALL_TARGET is is language-specific,
-          as is building the call which will perform the
-          initialization.  It is left here to show the choices that
-          exist for C++.  */
-          
-       if (AGGR_INIT_VIA_CTOR_P (exp))
-         {
-           type = build_pointer_type (type);
-           mark_addressable (slot);
-           args = tree_cons (NULL_TREE, 
-                             build1 (ADDR_EXPR, type, slot),
-                             TREE_CHAIN (args));
-           call_target = 0;
-         }
-       else
-         {
-           call_target = target;
-#ifdef PCC_STATIC_STRUCT_RETURN
-           if (aggregate_value_p (type))
-             {
-               pcc_struct_return = 1;
-               call_target = 0;
-             }
-#endif
-         }
-
-       call_exp = build (CALL_EXPR, type, func, args, NULL_TREE);
-       TREE_SIDE_EFFECTS (call_exp) = 1;
-       return_target = expand_call (call_exp, call_target, ignore);
-
-       if (call_target)
-         /* Trust that the right thing has been done; it's too hard to
-            verify.  */
-         return return_target;
-
-       /* If we're suffering under the ancient PCC_STATIC_STRUCT_RETURN
-          calling convention, we need to copy the return value out of
-          the static return buffer into slot.  */
-       if (pcc_struct_return)
-         {
-           extern int flag_access_control;
-           int old_ac = flag_access_control;
-
-           tree init = build_decl (VAR_DECL, NULL_TREE,
-                                   build_reference_type (type));
-           DECL_RTL (init) = XEXP (return_target, 0);
-           init = convert_from_reference (init);
-
-           flag_access_control = 0;
-           expand_expr (build_aggr_init (slot, init,
-                                         LOOKUP_ONLYCONVERTING), 
-                        target, tmode, EXPAND_NORMAL);
-           flag_access_control = old_ac;
-
-           if (TYPE_NEEDS_DESTRUCTOR (type))
-             {
-               init = maybe_build_cleanup (init);
-               if (init != NULL_TREE)
-                 expand_expr (init, const0_rtx, VOIDmode, 0);
-             }
-         }
-
-       return DECL_RTL (slot);
-      }
-
     case PTRMEM_CST:
       return expand_expr (cplus_expand_constant (exp),
                          target, tmode, modifier);
index 8637e3b670a9fd2b252202b08f25293d7f51d900..ca0201db58e2ce4e8ddbe7e8327de3459dd3f6e8 100644 (file)
@@ -2547,6 +2547,81 @@ expand_stmt (t)
   return rval;
 }
 
+/* Called from expand_body via walk_tree.  Replace all AGGR_INIT_EXPRs
+   will equivalent CALL_EXPRs.  */
+
+static tree
+simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
+     tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
+{
+  tree aggr_init_expr;
+  tree call_expr;
+  tree fn;
+  tree args;
+  tree slot;
+  tree type;
+  tree call_type;
+  int copy_from_buffer_p;
+
+  /* Only AGGR_INIT_EXPRs are interesting.  */
+  aggr_init_expr = *tp;
+  if (TREE_CODE (aggr_init_expr) != AGGR_INIT_EXPR)
+    return NULL_TREE;
+
+  /* Form an appropriate CALL_EXPR.  */
+  fn = TREE_OPERAND (aggr_init_expr, 0);
+  args = TREE_OPERAND (aggr_init_expr, 1);
+  slot = TREE_OPERAND (aggr_init_expr, 2);
+  type = TREE_TYPE (aggr_init_expr);
+  call_type = type;
+  if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
+    {
+      /* Replace the first argument with the address of the third
+        argument to the AGGR_INIT_EXPR.  */
+      call_type = build_pointer_type (type);
+      mark_addressable (slot);
+      args = tree_cons (NULL_TREE, build1 (ADDR_EXPR, call_type, slot),
+                       TREE_CHAIN (args));
+    }
+  call_expr = build (CALL_EXPR, call_type, fn, args, NULL_TREE);
+  TREE_SIDE_EFFECTS (call_expr) = 1;
+
+  /* If we're using the non-reentrant PCC calling convention, then we
+     need to copy the returned value out of the static buffer into the
+     SLOT.  */
+  copy_from_buffer_p = 0;
+#ifdef PCC_STATIC_STRUCT_RETURN  
+  if (!AGGR_INIT_VIA_CTOR_P (aggr_init_expr) && aggregate_value_p (type))
+    {
+      int old_ac;
+
+      flag_access_control = 0;
+      call_expr = build_aggr_init (slot, call_expr, LOOKUP_ONLYCONVERTING);
+      flag_access_control = old_ac;
+      copy_from_buffer_p = 1;
+    }
+#endif
+
+  /* If this AGGR_INIT_EXPR indicates the value returned by a
+     function, then we want to use the value of the initialized
+     location as the result.  */
+  if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr) || copy_from_buffer_p)
+    {
+      call_expr = build (COMPOUND_EXPR, type,
+                        call_expr, slot);
+      TREE_SIDE_EFFECTS (call_expr) = 1;
+    }
+
+  /* Replace the AGGR_INIT_EXPR with the CALL_EXPR.  */
+  TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
+  *tp = call_expr;
+
+  /* Keep iterating.  */
+  return NULL_TREE;
+}
+
 /* Generate RTL for FN.  */
 
 void
@@ -2574,6 +2649,9 @@ expand_body (fn)
       return;
     }
 
+  /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs.  */
+  walk_tree (&DECL_SAVED_TREE (fn), simplify_aggr_init_exprs_r, NULL);
+
   /* There's no reason to do any of the work here if we're only doing
      semantic analysis; this code just generates RTL.  */
   if (flag_syntax_only)
index 1cabf82c127ac92cf0e0a00ab065d843fa222b29..31fbec0401c07b9fdbe4300cee287ba8ca2c9c98 100644 (file)
@@ -1626,8 +1626,18 @@ walk_tree (tp, func, data)
       int i;
 
       /* Walk over all the sub-trees of this operand.  */
-      for (i = first_rtl_op (code) - 1; i >= 0; --i)
-       WALK_SUBTREE (TREE_OPERAND (*tp, i));
+      i = first_rtl_op (code) - 1;
+      /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same.
+        But, we only want to walk once.  */
+      if (code == TARGET_EXPR
+         && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1))
+       --i;
+      /* Go through the subtrees.  */
+      while (i >= 0)
+       {
+         WALK_SUBTREE (TREE_OPERAND (*tp, i));
+         --i;
+       }
 
       /* For statements, we also walk the chain so that we cover the
         entire statement tree.  */
diff --git a/gcc/testsuite/g++.old-deja/g++.other/inline1.C b/gcc/testsuite/g++.old-deja/g++.other/inline1.C
new file mode 100644 (file)
index 0000000..c4c71b7
--- /dev/null
@@ -0,0 +1,20 @@
+// Build don't link:
+// Origin: Martin Reinecke <martin@MPA-Garching.MPG.DE>
+// Special g++ Options: -O2 -Winline
+
+class foo
+{
+  public:
+    float x;
+
+    foo (float xval)
+      : x (xval) {}
+
+    foo operator+ (const foo &foo2) const
+      { return foo (x+foo2.x); }
+};
+
+int main()
+{
+  foo f=foo(1)+foo(2);
+}