diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index e37e71bd24f..010ecfc6b43 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -3182,12 +3182,13 @@ devirtualization_time_bonus (struct cgraph_node *node,
   return res;
 }
 
-/* Return time bonus incurred because of HINTS.  */
+/* Return time bonus incurred because of hints stored in CTX.  */
 
 static int
-hint_time_bonus (cgraph_node *node, ipa_hints hints)
+hint_time_bonus (cgraph_node *node, const ipa_call_context &ctx)
 {
   int result = 0;
+  ipa_hints hints = ctx.m_hints;
   if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride))
     result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus);
   return result;
@@ -3387,16 +3388,14 @@ perform_estimation_of_a_value (cgraph_node *node, ipa_call_arg_values *avals,
 			       int removable_params_cost, int est_move_cost,
 			       ipcp_value_base *val)
 {
-  int size, time_benefit;
-  sreal time, base_time;
-  ipa_hints hints;
+  int time_benefit;
 
   ipa_call_context ctx = ipa_call_context::for_cloned_node (node, avals);
-  ctx.estimate_size_and_time (&size, NULL, &time, &base_time, &hints);
+  ctx.estimate_size_and_time ();
 
-  base_time -= time;
-  if (base_time > 65535)
-    base_time = 65535;
+  sreal time_delta = ctx.m_nonspecialized_time - ctx.m_time;
+  if (time_delta > 65535)
+    time_delta = 65535;
 
   /* Extern inline functions have no cloning local time benefits because they
      will be inlined anyway.  The only reason to clone them is if it enables
@@ -3404,11 +3403,12 @@ perform_estimation_of_a_value (cgraph_node *node, ipa_call_arg_values *avals,
   if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl))
     time_benefit = 0;
   else
-    time_benefit = base_time.to_int ()
+    time_benefit = time_delta.to_int ()
       + devirtualization_time_bonus (node, avals)
-      + hint_time_bonus (node, hints)
+      + hint_time_bonus (node, ctx)
       + removable_params_cost + est_move_cost;
 
+  int size = ctx.m_size;
   gcc_checking_assert (size >=0);
   /* The inliner-heuristics based estimates may think that in certain
      contexts some functions do not have any size at all but we want
@@ -3463,24 +3463,22 @@ estimate_local_effects (struct cgraph_node *node)
       || (removable_params_cost && node->can_change_signature))
     {
       struct caller_statistics stats;
-      ipa_hints hints;
-      sreal time, base_time;
-      int size;
 
       init_caller_stats (&stats);
       node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats,
 					      false);
       ipa_call_context ctx = ipa_call_context::for_cloned_node (node, &avals);
-      ctx.estimate_size_and_time (&size, NULL, &time, &base_time, &hints);
+      ctx.estimate_size_and_time ();
 
-      time -= devirt_bonus;
-      time -= hint_time_bonus (node, hints);
-      time -= removable_params_cost;
-      size -= stats.n_calls * removable_params_cost;
+      sreal time = ctx.m_nonspecialized_time - ctx.m_time;
+      time += devirt_bonus;
+      time += hint_time_bonus (node, ctx);
+      time += removable_params_cost;
+      int size = ctx.m_size - stats.n_calls * removable_params_cost;
 
       if (dump_file)
 	fprintf (dump_file, " - context independent values, size: %i, "
-		 "time_benefit: %f\n", size, (base_time - time).to_double ());
+		 "time_benefit: %f\n", size, (time).to_double ());
 
       if (size <= 0 || node->local)
 	{
@@ -3491,8 +3489,7 @@ estimate_local_effects (struct cgraph_node *node)
 		     "known contexts, code not going to grow.\n");
 	}
       else if (good_cloning_opportunity_p (node,
-					   MIN ((base_time - time).to_int (),
-						65536),
+					   MIN ((time).to_int (), 65536),
 					   stats.freq_sum, stats.count_sum,
 					   size))
 	{
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 2a0f8ad37b2..eb58b143d1c 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -3281,18 +3281,19 @@ ipa_call_context
 {
 }
 
-/* Estimate size and time needed to execute call in the given context.
-   Additionally determine hints determined by the context.  Finally compute
-   minimal size needed for the call that is independent on the call context and
-   can be used for fast estimates.  Return the values in RET_SIZE,
-   RET_MIN_SIZE, RET_TIME and RET_HINTS.  */
+/* Estimate size needed to execute call in the given context and store it to
+   m_size, compute minimal size needed for the call that is independent on the
+   call context and can be used for fast estimates and store it to m_min_size.
+
+   If EST_TIMES is true, estimate time needed to execute call in the given
+   context, store it to m_time, and time needed when also calculating things
+   known to be constant in this context and store it to m_nonspecialized_time.
+
+   If EST_HINTS is true, also determine hints for this context and store them
+   to m_hints.  */
 
 void
-ipa_call_context::estimate_size_and_time (int *ret_size,
-					  int *ret_min_size,
-					  sreal *ret_time,
-					  sreal *ret_nonspecialized_time,
-					  ipa_hints *ret_hints)
+ipa_call_context::estimate_size_and_time (bool est_times, bool est_hints)
 {
   class ipa_fn_summary *info = ipa_fn_summaries->get (m_node);
   size_time_entry *e;
@@ -3322,8 +3323,8 @@ ipa_call_context::estimate_size_and_time (int *ret_size,
 
   if (m_node->callees || m_node->indirect_calls)
     estimate_calls_size_and_time (m_node, &size, &min_size,
-				  ret_time ? &time : NULL,
-				  ret_hints ? &hints : NULL, m_possible_truths,
+				  est_times ? &time : NULL,
+				  est_hints ? &hints : NULL, m_possible_truths,
 				  m_avals);
 
   sreal nonspecialized_time = time;
@@ -3350,7 +3351,7 @@ ipa_call_context::estimate_size_and_time (int *ret_size,
 	     known to be constant in a specialized setting.  */
 	  if (nonconst)
 	    size += e->size;
-	  if (!ret_time)
+	  if (!est_times)
 	    continue;
 	  nonspecialized_time += e->time;
 	  if (!nonconst)
@@ -3390,7 +3391,7 @@ ipa_call_context::estimate_size_and_time (int *ret_size,
   if (time > nonspecialized_time)
     time = nonspecialized_time;
 
-  if (ret_hints)
+  if (est_hints)
     {
       if (info->loop_iterations
 	  && !info->loop_iterations->evaluate (m_possible_truths))
@@ -3410,16 +3411,15 @@ ipa_call_context::estimate_size_and_time (int *ret_size,
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "\n   size:%i time:%f nonspec time:%f\n", (int) size,
 	     time.to_double (), nonspecialized_time.to_double ());
-  if (ret_time)
-    *ret_time = time;
-  if (ret_nonspecialized_time)
-    *ret_nonspecialized_time = nonspecialized_time;
-  if (ret_size)
-    *ret_size = size;
-  if (ret_min_size)
-    *ret_min_size = min_size;
-  if (ret_hints)
-    *ret_hints = hints;
+  m_size = size;
+  m_min_size = min_size;
+  if (est_times)
+    {
+      m_time = time;
+      m_nonspecialized_time = nonspecialized_time;
+    }
+  if (est_hints)
+    m_hints = hints;
   return;
 }
 
diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h
index 74a78d31391..6253e375e3b 100644
--- a/gcc/ipa-fnsummary.h
+++ b/gcc/ipa-fnsummary.h
@@ -312,16 +312,41 @@ public:
   : m_node(NULL)
   {
   }
-  void estimate_size_and_time (int *ret_size, int *ret_min_size,
-			       sreal *ret_time,
-			       sreal *ret_nonspecialized_time,
-			       ipa_hints *ret_hints);
+  void estimate_size_and_time (bool est_times, bool est_hints);
+
+  /* Estimate everything about a call in this context.  */
+  void estimate_size_and_time ()
+  {
+    estimate_size_and_time (true, true);
+  }
+
   void store_to_cache (ipa_node_context_cache_entry *cache) const;
   bool equivalent_to_p (const ipa_node_context_cache_entry &cache) const;
   bool exists_p ()
   {
     return m_node != NULL;
   }
+
+
+  /* The following metrics fields only contain valid contents after they have
+     been calculated by estimate_size_and_time (provided the function was
+     instructed to compute them).  */
+
+  /* Estimated size needed to execute call in the given context. */
+  int m_size = INT_MIN;
+  /* Minimal size needed for the call that is independent on the call context
+     and can be used for fast estimates.  */
+  int m_min_size = INT_MIN;
+
+  /* Estimated time needed to execute call in the given context.  */
+  sreal m_time;
+  /* Estimated time needed to execute the function when not ignoring
+     computations known to be constant in this context.  */
+  sreal m_nonspecialized_time;
+
+  /* Further discovered reasons why to inline or specialize the give calls.  */
+  ipa_hints m_hints = -1;
+
 private:
   /* Called function.  */
   cgraph_node *m_node;
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 9788ee346ac..706e4fffe4a 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -428,16 +428,10 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time)
 	      && !opt_for_fn (callee->decl, flag_profile_partial_training)
 	      && !callee->count.ipa_p ())
 	    {
-	      sreal chk_time, chk_nonspec_time;
-	      int chk_size, chk_min_size;
-
-	      ipa_hints chk_hints;
-	      ctx.estimate_size_and_time (&chk_size, &chk_min_size,
-					  &chk_time, &chk_nonspec_time,
-					  &chk_hints);
-	      gcc_assert (chk_size == size && chk_time == time
-		  	  && chk_nonspec_time == nonspec_time
-			  && chk_hints == hints);
+	      ctx.estimate_size_and_time ();
+	      gcc_assert (ctx.m_size == size && ctx.m_time == time
+		  	  && ctx.m_nonspecialized_time == nonspec_time
+			  && ctx.m_hints == hints);
 	    }
 	}
       else
@@ -450,18 +444,26 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time)
 	  else
 	    e = node_context_cache->get_create (callee);
 
-	  ctx.estimate_size_and_time (&size, &min_size,
-				      &time, &nonspec_time, &hints);
+	  ctx.estimate_size_and_time ();
 	  ctx.store_to_cache (&e->entry);
+	  size = ctx.m_size;
 	  e->entry.m_size = size;
+	  time = ctx.m_time;
 	  e->entry.m_time = time;
+	  nonspec_time = ctx.m_nonspecialized_time;
 	  e->entry.m_nonspec_time = nonspec_time;
+	  hints = ctx.m_hints;
 	  e->entry.m_hints = hints;
 	}
     }
   else
-    ctx.estimate_size_and_time (&size, &min_size,
-				&time, &nonspec_time, &hints);
+    {
+      ctx.estimate_size_and_time ();
+      size = ctx.m_size;
+      time = ctx.m_time;
+      nonspec_time = ctx.m_nonspecialized_time;
+      hints = ctx.m_hints;
+    }
 
   /* When we have profile feedback, we can quite safely identify hot
      edges and for those we disable size limits.  Don't do that when
@@ -524,7 +526,6 @@ ipa_remove_from_growth_caches (struct cgraph_edge *edge)
 int
 do_estimate_edge_size (struct cgraph_edge *edge)
 {
-  int size;
   ipa_call_arg_values avals;
 
   /* When we do caching, use do_estimate_edge_time to populate the entry.  */
@@ -532,7 +533,7 @@ do_estimate_edge_size (struct cgraph_edge *edge)
   if (edge_growth_cache != NULL)
     {
       do_estimate_edge_time (edge);
-      size = edge_growth_cache->get (edge)->size;
+      int size = edge_growth_cache->get (edge)->size;
       gcc_checking_assert (size);
       return size - (size > 0);
     }
@@ -541,8 +542,8 @@ do_estimate_edge_size (struct cgraph_edge *edge)
   gcc_checking_assert (edge->inline_failed);
   ipa_call_context ctx = ipa_call_context::for_inlined_edge (edge, vNULL,
 							     &avals);
-  ctx.estimate_size_and_time (&size, NULL, NULL, NULL, NULL);
-  return size;
+  ctx.estimate_size_and_time (false, false);
+  return ctx.m_size;
 }
 
 
@@ -552,7 +553,6 @@ do_estimate_edge_size (struct cgraph_edge *edge)
 ipa_hints
 do_estimate_edge_hints (struct cgraph_edge *edge)
 {
-  ipa_hints hints;
   ipa_call_arg_values avals;
 
   /* When we do caching, use do_estimate_edge_time to populate the entry.  */
@@ -560,7 +560,7 @@ do_estimate_edge_hints (struct cgraph_edge *edge)
   if (edge_growth_cache != NULL)
     {
       do_estimate_edge_time (edge);
-      hints = edge_growth_cache->get (edge)->hints;
+      ipa_hints hints = edge_growth_cache->get (edge)->hints;
       gcc_checking_assert (hints);
       return hints - 1;
     }
@@ -569,9 +569,8 @@ do_estimate_edge_hints (struct cgraph_edge *edge)
   gcc_checking_assert (edge->inline_failed);
   ipa_call_context ctx = ipa_call_context::for_inlined_edge (edge, vNULL,
 							     &avals);
-  ctx.estimate_size_and_time (NULL, NULL, NULL, NULL, &hints);
-  hints |= simple_edge_hints (edge);
-  return hints;
+  ctx.estimate_size_and_time (false, true);
+  return ctx.m_hints | simple_edge_hints (edge);
 }
 
 /* Estimate the size of NODE after inlining EDGE which should be an
