+2014-12-08 David Malcolm <dmalcolm@redhat.com>
+
+ PR jit/63854
+ * cgraph.h (xstrdup_for_dump): New function.
+ * cgraph.c (cgraph_node::get_create): Replace use of xstrdup
+ within fprintf with xstrdup_for_dump.
+ (cgraph_edge::make_speculative): Likewise.
+ (cgraph_edge::resolve_speculation): Likewise.
+ (cgraph_edge::redirect_call_stmt_to_callee): Likewise.
+ (cgraph_node::dump): Likewise.
+ * cgraphclones.c (symbol_table::materialize_all_clones): Likewise.
+ * ipa-cp.c (perhaps_add_new_callers): Likewise.
+ * ipa-inline.c (report_inline_failed_reason): Likewise.
+ (want_early_inline_function_p): Likewise.
+ (edge_badness): Likewise.
+ (update_edge_key): Likewise.
+ (flatten_function): Likewise.
+ (inline_always_inline_functions): Likewise.
+ * ipa-profile.c (ipa_profile): Likewise.
+ * ipa-prop.c (ipa_print_node_jump_functions): Likewise.
+ (ipa_make_edge_direct_to_target): Likewise.
+ (remove_described_reference): Likewise.
+ (propagate_controlled_uses): Likewise.
+ * ipa-utils.c (ipa_merge_profiles): Likewise.
+
2014-12-08 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR ipa/64049
if (dump_file)
fprintf (dump_file, "Introduced new external node "
"(%s/%i) and turned into root of the clone tree.\n",
- xstrdup (node->name ()), node->order);
+ xstrdup_for_dump (node->name ()), node->order);
}
else if (dump_file)
fprintf (dump_file, "Introduced new external node "
- "(%s/%i).\n", xstrdup (node->name ()),
+ "(%s/%i).\n", xstrdup_for_dump (node->name ()),
node->order);
return node;
}
{
fprintf (dump_file, "Indirect call -> speculative call"
" %s/%i => %s/%i\n",
- xstrdup (n->name ()), n->order,
- xstrdup (n2->name ()), n2->order);
+ xstrdup_for_dump (n->name ()), n->order,
+ xstrdup_for_dump (n2->name ()), n2->order);
}
speculative = true;
e2 = n->create_edge (n2, call_stmt, direct_count, direct_frequency);
{
fprintf (dump_file, "Speculative indirect call %s/%i => %s/%i has "
"turned out to have contradicting known target ",
- xstrdup (edge->caller->name ()), edge->caller->order,
- xstrdup (e2->callee->name ()), e2->callee->order);
+ xstrdup_for_dump (edge->caller->name ()),
+ edge->caller->order,
+ xstrdup_for_dump (e2->callee->name ()),
+ e2->callee->order);
print_generic_expr (dump_file, callee_decl, 0);
fprintf (dump_file, "\n");
}
else
{
fprintf (dump_file, "Removing speculative call %s/%i => %s/%i\n",
- xstrdup (edge->caller->name ()), edge->caller->order,
- xstrdup (e2->callee->name ()), e2->callee->order);
+ xstrdup_for_dump (edge->caller->name ()),
+ edge->caller->order,
+ xstrdup_for_dump (e2->callee->name ()),
+ e2->callee->order);
}
}
}
if (dump_file)
fprintf (dump_file, "Not expanding speculative call of %s/%i -> %s/%i\n"
"Type mismatch.\n",
- xstrdup (e->caller->name ()),
+ xstrdup_for_dump (e->caller->name ()),
e->caller->order,
- xstrdup (e->callee->name ()),
+ xstrdup_for_dump (e->callee->name ()),
e->callee->order);
e = e->resolve_speculation ();
/* We are producing the final function body and will throw away the
fprintf (dump_file,
"Expanding speculative call of %s/%i -> %s/%i count:"
"%"PRId64"\n",
- xstrdup (e->caller->name ()),
+ xstrdup_for_dump (e->caller->name ()),
e->caller->order,
- xstrdup (e->callee->name ()),
+ xstrdup_for_dump (e->callee->name ()),
e->callee->order,
(int64_t)e->count);
gcc_assert (e2->speculative);
if (symtab->dump_file)
{
fprintf (symtab->dump_file, "updating call of %s/%i -> %s/%i: ",
- xstrdup (e->caller->name ()), e->caller->order,
- xstrdup (e->callee->name ()), e->callee->order);
+ xstrdup_for_dump (e->caller->name ()), e->caller->order,
+ xstrdup_for_dump (e->callee->name ()), e->callee->order);
print_gimple_stmt (symtab->dump_file, e->call_stmt, 0, dump_flags);
if (e->callee->clone.combined_args_to_skip)
{
if (global.inlined_to)
fprintf (f, " Function %s/%i is inline copy in %s/%i\n",
- xstrdup (name ()),
+ xstrdup_for_dump (name ()),
order,
- xstrdup (global.inlined_to->name ()),
+ xstrdup_for_dump (global.inlined_to->name ()),
global.inlined_to->order);
if (clone_of)
fprintf (f, " Clone of %s/%i\n",
return node->local.local && node->instrumented_version->local.local;
}
+/* When using fprintf (or similar), problems can arise with
+ transient generated strings. Many string-generation APIs
+ only support one result being alive at once (e.g. by
+ returning a pointer to a statically-allocated buffer).
+
+ If there is more than one generated string within one
+ fprintf call: the first string gets evicted or overwritten
+ by the second, before fprintf is fully evaluated.
+ See e.g. PR/53136.
+
+ This function provides a workaround for this, by providing
+ a simple way to create copies of these transient strings,
+ without the need to have explicit cleanup:
+
+ fprintf (dumpfile, "string 1: %s string 2:%s\n",
+ xstrdup_for_dump (EXPR_1),
+ xstrdup_for_dump (EXPR_2));
+
+ This is actually a simple wrapper around ggc_strdup, but
+ the name documents the intent. We require that no GC can occur
+ within the fprintf call. */
+
+static inline const char *
+xstrdup_for_dump (const char *transient_str)
+{
+ return ggc_strdup (transient_str);
+}
+
#endif /* GCC_CGRAPH_H */
if (symtab->dump_file)
{
fprintf (symtab->dump_file, "cloning %s to %s\n",
- xstrdup (node->clone_of->name ()),
- xstrdup (node->name ()));
+ xstrdup_for_dump (node->clone_of->name ()),
+ xstrdup_for_dump (node->name ()));
if (node->clone.tree_map)
{
unsigned int i;
if (dump_file)
fprintf (dump_file, " - adding an extra caller %s/%i"
" of %s/%i\n",
- xstrdup (cs->caller->name ()),
+ xstrdup_for_dump (cs->caller->name ()),
cs->caller->order,
- xstrdup (val->spec_node->name ()),
+ xstrdup_for_dump (val->spec_node->name ()),
val->spec_node->order);
cs->redirect_callee_duplicating_thunks (val->spec_node);
if (dump_file)
{
fprintf (dump_file, " not inlinable: %s/%i -> %s/%i, %s\n",
- xstrdup (e->caller->name ()), e->caller->order,
- xstrdup (e->callee->name ()), e->callee->order,
+ xstrdup_for_dump (e->caller->name ()), e->caller->order,
+ xstrdup_for_dump (e->callee->name ()), e->callee->order,
cgraph_inline_failed_string (e->inline_failed));
}
}
if (dump_file)
fprintf (dump_file, " will not early inline: %s/%i->%s/%i, "
"call is cold and code would grow by %i\n",
- xstrdup (e->caller->name ()),
+ xstrdup_for_dump (e->caller->name ()),
e->caller->order,
- xstrdup (callee->name ()), callee->order,
+ xstrdup_for_dump (callee->name ()), callee->order,
growth);
want_inline = false;
}
if (dump_file)
fprintf (dump_file, " will not early inline: %s/%i->%s/%i, "
"growth %i exceeds --param early-inlining-insns\n",
- xstrdup (e->caller->name ()),
+ xstrdup_for_dump (e->caller->name ()),
e->caller->order,
- xstrdup (callee->name ()), callee->order,
+ xstrdup_for_dump (callee->name ()), callee->order,
growth);
want_inline = false;
}
fprintf (dump_file, " will not early inline: %s/%i->%s/%i, "
"growth %i exceeds --param early-inlining-insns "
"divided by number of calls\n",
- xstrdup (e->caller->name ()),
+ xstrdup_for_dump (e->caller->name ()),
e->caller->order,
- xstrdup (callee->name ()), callee->order,
+ xstrdup_for_dump (callee->name ()), callee->order,
growth);
want_inline = false;
}
if (dump)
{
fprintf (dump_file, " Badness calculation for %s/%i -> %s/%i\n",
- xstrdup (edge->caller->name ()),
+ xstrdup_for_dump (edge->caller->name ()),
edge->caller->order,
- xstrdup (callee->name ()),
+ xstrdup_for_dump (callee->name ()),
edge->callee->order);
fprintf (dump_file, " size growth %i, time %i ",
growth,
fprintf (dump_file,
" decreasing badness %s/%i -> %s/%i, %"PRId64
" to %"PRId64"\n",
- xstrdup (edge->caller->name ()),
+ xstrdup_for_dump (edge->caller->name ()),
edge->caller->order,
- xstrdup (edge->callee->name ()),
+ xstrdup_for_dump (edge->callee->name ()),
edge->callee->order,
n->get_key ().to_int (),
badness.to_int ());
{
fprintf (dump_file,
" enqueuing call %s/%i -> %s/%i, badness %"PRId64"\n",
- xstrdup (edge->caller->name ()),
+ xstrdup_for_dump (edge->caller->name ()),
edge->caller->order,
- xstrdup (edge->callee->name ()),
+ xstrdup_for_dump (edge->callee->name ()),
edge->callee->order,
badness.to_int ());
}
if (dump_file)
fprintf (dump_file,
"Not inlining %s into %s to avoid cycle.\n",
- xstrdup (callee->name ()),
- xstrdup (e->caller->name ()));
+ xstrdup_for_dump (callee->name ()),
+ xstrdup_for_dump (e->caller->name ()));
e->inline_failed = CIF_RECURSIVE_INLINING;
continue;
}
recursing through the original node if the node was cloned. */
if (dump_file)
fprintf (dump_file, " Inlining %s into %s.\n",
- xstrdup (callee->name ()),
- xstrdup (e->caller->name ()));
+ xstrdup_for_dump (callee->name ()),
+ xstrdup_for_dump (e->caller->name ()));
orig_callee = callee;
inline_call (e, true, NULL, NULL, false);
if (e->callee != orig_callee)
if (dump_file)
fprintf (dump_file, " Inlining %s into %s (always_inline).\n",
- xstrdup (e->callee->name ()),
- xstrdup (e->caller->name ()));
+ xstrdup_for_dump (e->callee->name ()),
+ xstrdup_for_dump (e->caller->name ()));
inline_call (e, true, NULL, NULL, false);
inlined = true;
}
if (dump_file)
fprintf (dump_file, " Inlining %s into %s.\n",
- xstrdup (callee->name ()),
- xstrdup (e->caller->name ()));
+ xstrdup_for_dump (callee->name ()),
+ xstrdup_for_dump (e->caller->name ()));
inline_call (e, true, NULL, NULL, true);
inlined = true;
}
{
fprintf (dump_file, "Indirect call -> direct call from"
" other module %s/%i => %s/%i, prob %3.2f\n",
- xstrdup (n->name ()), n->order,
- xstrdup (n2->name ()), n2->order,
+ xstrdup_for_dump (n->name ()), n->order,
+ xstrdup_for_dump (n2->name ()), n2->order,
e->indirect_info->common_target_probability
/ (float)REG_BR_PROB_BASE);
}
continue;
fprintf (f, " callsite %s/%i -> %s/%i : \n",
- xstrdup (node->name ()), node->order,
- xstrdup (cs->callee->name ()),
+ xstrdup_for_dump (node->name ()), node->order,
+ xstrdup_for_dump (cs->callee->name ()),
cs->callee->order);
ipa_print_node_jump_functions_for_edge (f, cs);
}
if (dump_file)
fprintf (dump_file, "ipa-prop: Discovered call to a known target "
"(%s/%i -> %s/%i) but can not refer to it. Giving up.\n",
- xstrdup (ie->caller->name ()),
+ xstrdup_for_dump (ie->caller->name ()),
ie->caller->order,
- xstrdup (ie->callee->name ()),
+ xstrdup_for_dump (ie->callee->name ()),
ie->callee->order);
return NULL;
}
if (dump_file)
fprintf (dump_file, "ipa-prop: Discovered call to a speculative target "
"(%s/%i -> %s/%i) but the call is already speculated to %s/%i. Giving up.\n",
- xstrdup (ie->caller->name ()),
+ xstrdup_for_dump (ie->caller->name ()),
ie->caller->order,
- xstrdup (callee->name ()),
+ xstrdup_for_dump (callee->name ()),
callee->order,
- xstrdup (e2->callee->name ()),
+ xstrdup_for_dump (e2->callee->name ()),
e2->callee->order);
}
else
if (dump_file)
fprintf (dump_file, "ipa-prop: Discovered call to a speculative target "
"(%s/%i -> %s/%i) this agree with previous speculation.\n",
- xstrdup (ie->caller->name ()),
+ xstrdup_for_dump (ie->caller->name ()),
ie->caller->order,
- xstrdup (callee->name ()),
+ xstrdup_for_dump (callee->name ()),
callee->order);
}
return NULL;
"(%s/%i -> %s/%i), for stmt ",
ie->indirect_info->polymorphic ? "a virtual" : "an indirect",
speculative ? "speculative" : "known",
- xstrdup (ie->caller->name ()),
+ xstrdup_for_dump (ie->caller->name ()),
ie->caller->order,
- xstrdup (callee->name ()),
+ xstrdup_for_dump (callee->name ()),
callee->order);
if (ie->call_stmt)
print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM);
to_del->remove_reference ();
if (dump_file)
fprintf (dump_file, "ipa-prop: Removed a reference from %s/%i to %s.\n",
- xstrdup (origin->caller->name ()),
- origin->caller->order, xstrdup (symbol->name ()));
+ xstrdup_for_dump (origin->caller->name ()),
+ origin->caller->order, xstrdup_for_dump (symbol->name ()));
return true;
}
if (dump_file)
fprintf (dump_file, "ipa-prop: Removing cloning-created "
"reference from %s/%i to %s/%i.\n",
- xstrdup (new_root->name ()),
+ xstrdup_for_dump (new_root->name ()),
new_root->order,
- xstrdup (n->name ()), n->order);
+ xstrdup_for_dump (n->name ()), n->order);
ref->remove_reference ();
}
}
fprintf (dump_file, "ipa-prop: Removing "
"cloning-created reference "
"from %s/%i to %s/%i.\n",
- xstrdup (clone->name ()),
+ xstrdup_for_dump (clone->name ()),
clone->order,
- xstrdup (n->name ()),
+ xstrdup_for_dump (n->name ()),
n->order);
ref->remove_reference ();
}
if (symtab->dump_file)
{
fprintf (symtab->dump_file, "Merging profiles of %s/%i to %s/%i\n",
- xstrdup (src->name ()), src->order,
- xstrdup (dst->name ()), dst->order);
+ xstrdup_for_dump (src->name ()), src->order,
+ xstrdup_for_dump (dst->name ()), dst->order);
}
dst->count += src->count;