if (dump_file)
{
fprintf (dump_file, " not inlinable: %s/%i -> %s/%i, %s\n",
- cgraph_node_name (e->caller), e->caller->uid,
- cgraph_node_name (e->callee), e->callee->uid,
+ xstrdup (cgraph_node_name (e->caller)), e->caller->uid,
+ xstrdup (cgraph_node_name (e->callee)), e->callee->uid,
cgraph_inline_failed_string (e->inline_failed));
}
}
e->inline_failed = CIF_EH_PERSONALITY;
inlinable = false;
}
+ /* TM pure functions should not be inlined into non-TM_pure
+ functions. */
+ else if (is_tm_pure (callee->decl)
+ && !is_tm_pure (e->caller->decl))
+ {
+ e->inline_failed = CIF_UNSPECIFIED;
+ inlinable = false;
+ }
/* Don't inline if the callee can throw non-call exceptions but the
caller cannot.
FIXME: this is obviously wrong for LTO where STRUCT_FUNCTION is missing.
}
}
- /* Be sure that the cannot_inline_p flag is up to date. */
- gcc_checking_assert (!e->call_stmt
- || (gimple_call_cannot_inline_p (e->call_stmt)
- == e->call_stmt_cannot_inline_p)
- /* In -flto-partition=none mode we really keep things out of
- sync because call_stmt_cannot_inline_p is set at cgraph
- merging when function bodies are not there yet. */
- || (in_lto_p && !gimple_call_cannot_inline_p (e->call_stmt)));
if (!inlinable && report)
report_inline_failed_reason (e);
return inlinable;
if (dump_file)
fprintf (dump_file, " will not early inline: %s/%i->%s/%i, "
"call is cold and code would grow by %i\n",
- cgraph_node_name (e->caller), e->caller->uid,
- cgraph_node_name (callee), callee->uid,
+ xstrdup (cgraph_node_name (e->caller)), e->caller->uid,
+ xstrdup (cgraph_node_name (callee)), callee->uid,
growth);
want_inline = false;
}
if (dump_file)
fprintf (dump_file, " will not early inline: %s/%i->%s/%i, "
"callee is not leaf and code would grow by %i\n",
- cgraph_node_name (e->caller), e->caller->uid,
- cgraph_node_name (callee), callee->uid,
+ xstrdup (cgraph_node_name (e->caller)), e->caller->uid,
+ xstrdup (cgraph_node_name (callee)), callee->uid,
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",
- cgraph_node_name (e->caller), e->caller->uid,
- cgraph_node_name (callee), callee->uid,
+ xstrdup (cgraph_node_name (e->caller)), e->caller->uid,
+ xstrdup (cgraph_node_name (callee)), callee->uid,
growth);
want_inline = false;
}
e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
want_inline = false;
}
- else if (!DECL_DECLARED_INLINE_P (callee->decl)
- && !flag_inline_functions)
- {
- e->inline_failed = CIF_NOT_DECLARED_INLINED;
- want_inline = false;
- }
- else if (!DECL_DECLARED_INLINE_P (callee->decl)
- && growth >= MAX_INLINE_INSNS_AUTO)
- {
- e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
- want_inline = false;
- }
- /* If call is cold, do not inline when function body would grow.
- Still inline when the overall unit size will shrink because the offline
- copy of function being eliminated.
+ /* Before giving up based on fact that caller size will grow, allow
+ functions that are called few times and eliminating the offline
+ copy will lead to overall code size reduction.
+ Not all of these will be handled by subsequent inlining of functions
+ called once: in particular weak functions are not handled or funcitons
+ that inline to multiple calls but a lot of bodies is optimized out.
+ Finally we want to inline earlier to allow inlining of callbacks.
This is slightly wrong on aggressive side: it is entirely possible
that function is called many times with a context where inlining
first, this situation is not a problem at all: after inlining all
"good" calls, we will realize that keeping the function around is
better. */
- else if (!cgraph_maybe_hot_edge_p (e)
- && (DECL_EXTERNAL (callee->decl)
-
- /* Unlike for functions called once, we play unsafe with
- COMDATs. We can allow that since we know functions
- in consideration are small (and thus risk is small) and
- moreover grow estimates already accounts that COMDAT
- functions may or may not disappear when eliminated from
- current unit. With good probability making aggressive
- choice in all units is going to make overall program
- smaller.
-
- Consequently we ask cgraph_can_remove_if_no_direct_calls_p
- instead of
- cgraph_will_be_removed_from_program_if_no_direct_calls */
-
- || !cgraph_can_remove_if_no_direct_calls_p (callee)
- || estimate_growth (callee) > 0))
+ else if (growth <= MAX_INLINE_INSNS_SINGLE
+ /* Unlike for functions called once, we play unsafe with
+ COMDATs. We can allow that since we know functions
+ in consideration are small (and thus risk is small) and
+ moreover grow estimates already accounts that COMDAT
+ functions may or may not disappear when eliminated from
+ current unit. With good probability making aggressive
+ choice in all units is going to make overall program
+ smaller.
+
+ Consequently we ask cgraph_can_remove_if_no_direct_calls_p
+ instead of
+ cgraph_will_be_removed_from_program_if_no_direct_calls */
+ && !DECL_EXTERNAL (callee->decl)
+ && cgraph_can_remove_if_no_direct_calls_p (callee)
+ && estimate_growth (callee) <= 0)
+ ;
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
+ && !flag_inline_functions)
+ {
+ e->inline_failed = CIF_NOT_DECLARED_INLINED;
+ want_inline = false;
+ }
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
+ && growth >= MAX_INLINE_INSNS_AUTO)
+ {
+ e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
+ want_inline = false;
+ }
+ /* If call is cold, do not inline when function body would grow. */
+ else if (!cgraph_maybe_hot_edge_p (e))
{
e->inline_failed = CIF_UNLIKELY_CALL;
want_inline = false;
if (dump)
{
fprintf (dump_file, " Badness calculation for %s -> %s\n",
- cgraph_node_name (edge->caller),
- cgraph_node_name (callee));
+ xstrdup (cgraph_node_name (edge->caller)),
+ xstrdup (cgraph_node_name (callee)));
fprintf (dump_file, " size growth %i, time growth %i\n",
growth,
time_growth);
else if (flag_guess_branch_prob)
{
int div = edge->frequency * (1<<10) / CGRAPH_FREQ_MAX;
- int growth_for_all;
div = MAX (div, 1);
gcc_checking_assert (edge->frequency <= CGRAPH_FREQ_MAX);
if (dump)
fprintf (dump_file, "Badness overflow\n");
}
- growth_for_all = estimate_growth (callee);
- badness += growth_for_all;
if (dump)
{
fprintf (dump_file,
- " %i: guessed profile. frequency %f, overall growth %i,"
+ " %i: guessed profile. frequency %f,"
" benefit %f%%, divisor %i\n",
- (int) badness, (double)edge->frequency / CGRAPH_FREQ_BASE, growth_for_all,
+ (int) badness, (double)edge->frequency / CGRAPH_FREQ_BASE,
relative_time_benefit (callee_info, edge, time_growth) * 100 / 256.0, div);
}
}
else
{
int nest = MIN (inline_edge_summary (edge)->loop_depth, 8);
- badness = estimate_growth (callee) * 256;
+ badness = growth * 256;
/* Decrease badness if call is nested. */
if (badness > 0)
{
fprintf (dump_file,
" decreasing badness %s/%i -> %s/%i, %i to %i\n",
- cgraph_node_name (edge->caller), edge->caller->uid,
- cgraph_node_name (edge->callee), edge->callee->uid,
+ xstrdup (cgraph_node_name (edge->caller)),
+ edge->caller->uid,
+ xstrdup (cgraph_node_name (edge->callee)),
+ edge->callee->uid,
(int)n->key,
badness);
}
{
fprintf (dump_file,
" enqueuing call %s/%i -> %s/%i, badness %i\n",
- cgraph_node_name (edge->caller), edge->caller->uid,
- cgraph_node_name (edge->callee), edge->callee->uid,
+ xstrdup (cgraph_node_name (edge->caller)),
+ edge->caller->uid,
+ xstrdup (cgraph_node_name (edge->callee)),
+ edge->callee->uid,
badness);
}
edge->aux = fibheap_insert (heap, badness, edge);
if (dump_file)
fprintf (dump_file,
"Not inlining %s into %s to avoid cycle.\n",
- cgraph_node_name (callee),
- cgraph_node_name (e->caller));
+ xstrdup (cgraph_node_name (callee)),
+ xstrdup (cgraph_node_name (e->caller)));
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",
- cgraph_node_name (callee),
- cgraph_node_name (e->caller));
+ xstrdup (cgraph_node_name (callee)),
+ xstrdup (cgraph_node_name (e->caller)));
orig_callee = callee;
inline_call (e, true, NULL, NULL);
if (e->callee != orig_callee)
{
fprintf (dump_file,
"\nInlining %s size %i.\n",
- cgraph_node_name (node), inline_summary (node)->size);
+ cgraph_node_name (node),
+ inline_summary (node)->size);
fprintf (dump_file,
" Called once from %s %i insns.\n",
cgraph_node_name (node->callers->caller),
if (dump_file)
fprintf (dump_file, " Inlining %s into %s (always_inline).\n",
- cgraph_node_name (e->callee),
- cgraph_node_name (e->caller));
+ xstrdup (cgraph_node_name (e->callee)),
+ xstrdup (cgraph_node_name (e->caller)));
inline_call (e, true, NULL, NULL);
inlined = true;
}
if (dump_file)
fprintf (dump_file, " Inlining %s into %s.\n",
- cgraph_node_name (callee),
- cgraph_node_name (e->caller));
+ xstrdup (cgraph_node_name (callee)),
+ xstrdup (cgraph_node_name (e->caller)));
inline_call (e, true, NULL, NULL);
inlined = true;
}
= estimate_num_insns (edge->call_stmt, &eni_size_weights);
es->call_stmt_time
= estimate_num_insns (edge->call_stmt, &eni_time_weights);
+ if (edge->callee->decl
+ && !gimple_check_call_matching_types (edge->call_stmt,
+ edge->callee->decl))
+ edge->call_stmt_cannot_inline_p = true;
}
timevar_pop (TV_INTEGRATION);
iterations++;