+2015-12-10  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-cp.c (ipcp_cloning_candidate_p): Use node->optimize_for_size_p.
+       (good_cloning_opportunity_p): Likewise.
+       (gather_context_independent_values): Do not return true when
+       polymorphic call context is known or when we have known aggregate
+       value of unused parameter.
+       (estimate_local_effects): Try to create clone for all context
+       when either some params are substituted or devirtualization is possible
+       or some params can be removed; use local flag instead of
+       node->will_be_removed_from_program_if_no_direct_calls_p.
+       (identify_dead_nodes): Likewise.
+
 2015-12-10  David Malcolm  <dmalcolm@redhat.com>
 
        * doc/invoke.texi (-Wall): Add -Wmisleading-indentation to the
 
       return false;
     }
 
-  if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
+  if (node->optimize_for_size_p ())
     {
       if (dump_file)
         fprintf (dump_file, "Not considering %s for cloning; "
 {
   if (time_benefit == 0
       || !opt_for_fn (node->decl, flag_ipa_cp_clone)
-      || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
+      || node->optimize_for_size_p ())
     return false;
 
   gcc_assert (size_cost > 0);
        *removable_params_cost
          += ipa_get_param_move_cost (info, i);
 
+      if (!ipa_is_param_used (info, i))
+       continue;
+
       ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat;
+      /* Do not account known context as reason for cloning.  We can see
+        if it permits devirtualization.  */
       if (ctxlat->is_single_const ())
-       {
-         (*known_contexts)[i] = ctxlat->values->value;
-         ret = true;
-       }
+       (*known_contexts)[i] = ctxlat->values->value;
 
       if (known_aggs)
        {
                                                    &known_contexts, &known_aggs,
                                                    &removable_params_cost);
   known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs);
-  if (always_const)
+  int devirt_bonus = devirtualization_time_bonus (node, known_csts,
+                                          known_contexts, known_aggs_ptrs);
+  if (always_const || devirt_bonus || removable_params_cost)
     {
       struct caller_statistics stats;
       inline_hints hints;
                                              false);
       estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts,
                                         known_aggs_ptrs, &size, &time, &hints);
-      time -= devirtualization_time_bonus (node, known_csts, known_contexts,
-                                          known_aggs_ptrs);
+      time -= devirt_bonus;
       time -= hint_time_bonus (hints);
       time -= removable_params_cost;
       size -= stats.n_calls * removable_params_cost;
        fprintf (dump_file, " - context independent values, size: %i, "
                 "time_benefit: %i\n", size, base_time - time);
 
-      if (size <= 0
-         || node->will_be_removed_from_program_if_no_direct_calls_p ())
+      if (size <= 0 || node->local.local)
        {
          info->do_clone_for_all_contexts = true;
          base_time = time;
                     "max_new_size would be reached with %li.\n",
                     size + overall_size);
        }
+      else if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "   Not cloning for all contexts because "
+                "!good_cloning_opportunity_p.\n");
+       
     }
 
   for (i = 0; i < count ; i++)
 {
   struct cgraph_node *v;
   for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
-    if (v->will_be_removed_from_program_if_no_direct_calls_p ()
+    if (v->local.local
        && !v->call_for_symbol_thunks_and_aliases
             (has_undead_caller_from_outside_scc_p, NULL, true))
       IPA_NODE_REF (v)->node_dead = 1;