+2015-04-11 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/65743
+ * ipa-inline-transform.c (speculation_removed): Remove static var.
+ (check_speculations): New function.
+ (clone_inlined_nodes): Do not check spculations.
+ (inline_call): Call check_speculations.
+ * ipa-prop.c (ipa_make_edge_direct_to_target): Do not
+ consider non-invariants.
+
2015-04-11 Jan Hubicka <hubicka@ucw.cz>
Martin Liska <mliska@suse.cz>
int ncalls_inlined;
int nfunctions_inlined;
-bool speculation_removed;
/* Scale frequency of NODE edges by FREQ_SCALE. */
next = e->next_callee;
if (!e->inline_failed)
clone_inlined_nodes (e, duplicate, update_original, overall_size, freq_scale);
+ }
+}
+
+/* Check all speculations in N and resolve them if they seems useless. */
+
+static bool
+check_speculations (cgraph_node *n)
+{
+ bool speculation_removed = false;
+ cgraph_edge *next;
+
+ for (cgraph_edge *e = n->callees; e; e = next)
+ {
+ next = e->next_callee;
if (e->speculative && !speculation_useful_p (e, true))
{
e->resolve_speculation (NULL);
speculation_removed = true;
}
+ else if (!e->inline_failed)
+ speculation_removed |= check_speculations (e->callee);
}
+ return speculation_removed;
}
/* Mark all call graph edges coming out of NODE and all nodes that have been
bool predicated = inline_edge_summary (e)->predicate != NULL;
#endif
- speculation_removed = false;
/* Don't inline inlined edges. */
gcc_assert (e->inline_failed);
/* Don't even think of inlining inline clone. */
mark_all_inlined_calls_cdtor (e->callee);
if (opt_for_fn (e->caller->decl, optimize))
new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
+ check_speculations (e->callee);
if (update_overall_summary)
inline_update_overall_summary (to);
new_size = inline_summaries->get (to)->size;
target = canonicalize_constructor_val (target, NULL);
if (!target || TREE_CODE (target) != FUNCTION_DECL)
{
- if (ie->indirect_info->member_ptr)
- /* Member pointer call that goes through a VMT lookup. */
- return NULL;
+ /* Member pointer call that goes through a VMT lookup. */
+ if (ie->indirect_info->member_ptr
+ /* Or if target is not an invariant expression and we do not
+ know if it will evaulate to function at runtime.
+ This can happen when folding through &VAR, where &VAR
+ is IP invariant, but VAR itself is not.
+
+ TODO: Revisit this when GCC 5 is branched. It seems that
+ member_ptr check is not needed and that we may try to fold
+ the expression and see if VAR is readonly. */
+ || !is_gimple_ip_invariant (target))
+ {
+ if (dump_enabled_p ())
+ {
+ location_t loc = gimple_location_safe (ie->call_stmt);
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
+ "discovered direct call non-invariant "
+ "%s/%i\n",
+ ie->caller->name (), ie->caller->order);
+ }
+ return NULL;
+ }
+
if (dump_enabled_p ())
{