cgraph.c (thunk_adjust): Export.
authorJan Hubicka <hubicka@ucw.cz>
Sun, 8 May 2016 18:44:02 +0000 (20:44 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 8 May 2016 18:44:02 +0000 (18:44 +0000)
* cgraph.c (thunk_adjust): Export.
* cgraphclones.c (cgraph_node::create_clone): Clone thunk info.
* cgraphunit.c (thunk_adjust): Export.
(cgraph_node::assemble_thunks_and_aliases): Do not assemble inlined
thunks.
* ipa-inline-analyssi.c (compute_inline_parameters): Thunks are
inlinable.
* tree-inline.c (expand_call_inline): Expand thunks inline.

From-SVN: r236012

gcc/ChangeLog
gcc/cgraph.h
gcc/cgraphclones.c
gcc/cgraphunit.c
gcc/ipa-inline-analysis.c
gcc/tree-inline.c

index c562800bee187357263523b2c14d9e3dc49672e9..1f985ce00e55eff036dc24ccb99660a1a99c8617 100644 (file)
@@ -1,3 +1,14 @@
+2016-05-08  Jan Hubicka  <hubicka@ucw.cz>
+
+       * cgraph.c (thunk_adjust): Export.
+       * cgraphclones.c (cgraph_node::create_clone): Clone thunk info.
+       * cgraphunit.c (thunk_adjust): Export.
+       (cgraph_node::assemble_thunks_and_aliases): Do not assemble inlined
+       thunks.
+       * ipa-inline-analyssi.c (compute_inline_parameters): Thunks are
+       inlinable.
+       * tree-inline.c (expand_call_inline): Expand thunks inline.
+
 2016-05-08  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/70998
index d714ad75189f8daf5ee845b3e9510ebfcea64466..8ad9f456a22e57767e92b5c04787087bc8227535 100644 (file)
@@ -2299,6 +2299,7 @@ void cgraphunit_c_finalize (void);
     IN_SSA is true if the gimple is in SSA.  */
 basic_block init_lowered_empty_function (tree, bool, gcov_type);
 
+tree thunk_adjust (gimple_stmt_iterator *, tree, bool, HOST_WIDE_INT, tree);
 /* In cgraphclones.c  */
 
 tree clone_function_name_1 (const char *, const char *);
index 10f2d3417f47e41528d50f8bc65bee5afc2d9c58..43ee7352e5b09ae086672629b0352071a8947698 100644 (file)
@@ -436,6 +436,7 @@ cgraph_node::create_clone (tree new_decl, gcov_type gcov_count, int freq,
   new_node->tm_clone = tm_clone;
   new_node->icf_merged = icf_merged;
   new_node->merged_comdat = merged_comdat;
+  new_node->thunk = thunk;
 
   new_node->clone.tree_map = NULL;
   new_node->clone.args_to_skip = args_to_skip;
index 57618807c490433d09ccea3f49982afc076f3150..4bfcad78f59865e50f533d1547b69fd0e56b94df 100644 (file)
@@ -1471,7 +1471,7 @@ init_lowered_empty_function (tree decl, bool in_ssa, gcov_type count)
    non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and
    zero for a result adjusting thunk.  */
 
-static tree
+tree
 thunk_adjust (gimple_stmt_iterator * bsi,
              tree ptr, bool this_adjusting,
              HOST_WIDE_INT fixed_offset, tree virtual_offset)
@@ -1907,6 +1907,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
 
   for (e = callers; e;)
     if (e->caller->thunk.thunk_p
+       && !e->caller->global.inlined_to
        && !e->caller->thunk.add_pointer_bounds_args)
       {
        cgraph_node *thunk = e->caller;
index 47b5b96ace4db0121323c2b8bad78728f2d7d233..17b21d17c5f41187712c10f04d095eefdd92618b 100644 (file)
@@ -2920,67 +2920,70 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
   info = inline_summaries->get (node);
   reset_inline_summary (node, info);
 
-  /* FIXME: Thunks are inlinable, but tree-inline don't know how to do that.
-     Once this happen, we will need to more curefully predict call
-     statement size.  */
+  /* Estimate the stack size for the function if we're optimizing.  */
+  self_stack_size = optimize && !node->thunk.thunk_p
+                   ? estimated_stack_frame_size (node) : 0;
+  info->estimated_self_stack_size = self_stack_size;
+  info->estimated_stack_size = self_stack_size;
+  info->stack_frame_offset = 0;
+
   if (node->thunk.thunk_p)
     {
       struct inline_edge_summary *es = inline_edge_summary (node->callees);
       struct predicate t = true_predicate ();
 
-      info->inlinable = 0;
       node->callees->inline_failed = CIF_THUNK;
       node->local.can_change_signature = false;
-      es->call_stmt_time = 1;
-      es->call_stmt_size = 1;
-      account_size_time (info, 0, 0, &t);
-      return;
+      es->call_stmt_size = INLINE_SIZE_SCALE;
+      es->call_stmt_time = INLINE_TIME_SCALE;
+      account_size_time (info, INLINE_SIZE_SCALE * 2, INLINE_TIME_SCALE * 2, &t);
+      inline_update_overall_summary (node);
+      info->self_size = info->size;
+      info->self_time = info->time;
+      /* We can not inline instrumetnation clones.  */
+      info->inlinable = !node->thunk.add_pointer_bounds_args;
     }
-
-  /* Even is_gimple_min_invariant rely on current_function_decl.  */
-  push_cfun (DECL_STRUCT_FUNCTION (node->decl));
-
-  /* Estimate the stack size for the function if we're optimizing.  */
-  self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
-  info->estimated_self_stack_size = self_stack_size;
-  info->estimated_stack_size = self_stack_size;
-  info->stack_frame_offset = 0;
-
-  /* Can this function be inlined at all?  */
-  if (!opt_for_fn (node->decl, optimize)
-      && !lookup_attribute ("always_inline",
-                           DECL_ATTRIBUTES (node->decl)))
-    info->inlinable = false;
-  else
-    info->inlinable = tree_inlinable_function_p (node->decl);
-
-  info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun);
-
-  /* Type attributes can use parameter indices to describe them.  */
-  if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
-    node->local.can_change_signature = false;
   else
     {
-      /* Otherwise, inlinable functions always can change signature.  */
-      if (info->inlinable)
-       node->local.can_change_signature = true;
-      else
-       {
-         /* Functions calling builtin_apply can not change signature.  */
-         for (e = node->callees; e; e = e->next_callee)
-           {
-             tree cdecl = e->callee->decl;
-             if (DECL_BUILT_IN (cdecl)
-                 && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL
-                 && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS
-                     || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START))
-               break;
-           }
-         node->local.can_change_signature = !e;
-       }
-    }
-  estimate_function_body_sizes (node, early);
-
+       /* Even is_gimple_min_invariant rely on current_function_decl.  */
+       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+
+       /* Can this function be inlined at all?  */
+       if (!opt_for_fn (node->decl, optimize)
+          && !lookup_attribute ("always_inline",
+                                DECL_ATTRIBUTES (node->decl)))
+        info->inlinable = false;
+       else
+        info->inlinable = tree_inlinable_function_p (node->decl);
+
+       info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun);
+
+       /* Type attributes can use parameter indices to describe them.  */
+       if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
+        node->local.can_change_signature = false;
+       else
+        {
+          /* Otherwise, inlinable functions always can change signature.  */
+          if (info->inlinable)
+            node->local.can_change_signature = true;
+          else
+            {
+              /* Functions calling builtin_apply can not change signature.  */
+              for (e = node->callees; e; e = e->next_callee)
+                {
+                  tree cdecl = e->callee->decl;
+                  if (DECL_BUILT_IN (cdecl)
+                      && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL
+                      && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS
+                          || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START))
+                    break;
+                }
+              node->local.can_change_signature = !e;
+            }
+        }
+       estimate_function_body_sizes (node, early);
+       pop_cfun ();
+     }
   for (e = node->callees; e; e = e->next_callee)
     if (e->callee->comdat_local_p ())
       break;
@@ -2997,8 +3000,6 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
       gcc_assert (info->time == info->self_time
                  && info->size == info->self_size);
     }
-
-  pop_cfun ();
 }
 
 
index da233b29c4f49b9714826d0afb9ac0c90b0d4dbd..2ee3f630b147e31db1fb42343ba0e24f655804b2 100644 (file)
@@ -4450,6 +4450,43 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
        }
       goto egress;
     }
+  id->src_node = cg_edge->callee;
+
+  /* If callee is thunk, all we need is to adjust the THIS pointer
+     and redirect to function being thunked.  */
+  if (id->src_node->thunk.thunk_p)
+    {
+      cgraph_edge *edge;
+      tree virtual_offset = NULL;
+      int freq = cg_edge->frequency;
+      gcov_type count = cg_edge->count;
+      tree op;
+      gimple_stmt_iterator iter = gsi_for_stmt (stmt);
+
+      cg_edge->remove ();
+      edge = id->src_node->callees->clone (id->dst_node, call_stmt,
+                                          gimple_uid (stmt),
+                                          REG_BR_PROB_BASE, CGRAPH_FREQ_BASE,
+                                          true);
+      edge->frequency = freq;
+      edge->count = count;
+      if (id->src_node->thunk.virtual_offset_p)
+        virtual_offset = size_int (id->src_node->thunk.virtual_value);
+      op = create_tmp_reg_fn (cfun, TREE_TYPE (gimple_call_arg (stmt, 0)),
+                             NULL);
+      gsi_insert_before (&iter, gimple_build_assign (op,
+                                                   gimple_call_arg (stmt, 0)),
+                        GSI_NEW_STMT);
+      gcc_assert (id->src_node->thunk.this_adjusting);
+      op = thunk_adjust (&iter, op, 1, id->src_node->thunk.fixed_offset,
+                        virtual_offset);
+
+      gimple_call_set_arg (stmt, 0, op);
+      gimple_call_set_fndecl (stmt, edge->callee->decl);
+      update_stmt (stmt);
+      id->src_node->remove ();
+      return true;
+    }
   fn = cg_edge->callee->decl;
   cg_edge->callee->get_untransformed_body ();
 
@@ -4523,7 +4560,6 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
 
   /* Record the function we are about to inline.  */
   id->src_fn = fn;
-  id->src_node = cg_edge->callee;
   id->src_cfun = DECL_STRUCT_FUNCTION (fn);
   id->call_stmt = stmt;