* Fix can_inline_edge_p and code marking calls unreachable
@ 2015-03-26 18:32 Jan Hubicka
2015-03-26 21:12 ` Jan Hubicka
0 siblings, 1 reply; 8+ messages in thread
From: Jan Hubicka @ 2015-03-26 18:32 UTC (permalink / raw)
To: gcc-patches
Hi,
this patch fixes several issues in the inliner. First is the fact that
edge_set_predicate does not mark indirect and speculative edge as unreachable
correctly (found by my updated verification patch).
Other issue is that can_inline_edge_p was wrong in several ways. It did
use DECL_STRUCT_FUNCTION to check cilk and non-call-exceptions. THis does
not work with LTO. I also misupdated Richard's code to avoid inlining across
optimization boundaries so it did not check anoything and finally I noticed
we need to also check flag_exceptions. Inlining flag_exceptions function that
can throw into !flag_exceptions is leading to a wrong code. This also made
me notice that we do not correctly maintain DECL_FUNCTION_PERSONALITY.
After we decide to inline function with DECL_FUNCTION_PERSONALITY into a function
without DECL_FUNCTION_PERSONALITY, the caller inherits callee's perosnality.
This is done by tree-inline but it is too late and won't prevent us to mix different
personalities within one caller that has no personality.
Bootstrapped/regtested x86_64-linux, will commit it after testing on firefox.
Honza
* ipa-inline-analysis.c (redirect_to_unreachable): New function.
(edge_set_predicate): Use it to mark unreachable edges.
(inline_summary_t::duplicate): Remove unnecesary code.
(remap_edge_summaries): Likewise.
(dump_inline_summary): Report contains_cilk_spawn.
(compute_inline_parameters): Compute contains_cilk_spawn.
(inline_read_section, inline_write_summary): Stream
contains_cilk_spawn.
* ipa-inline.c (can_inline_edge_p): Do not tuch
DECL_STRUCT_FUNCTION that may not be available;
use CIF_CILK_SPAWN for cilk; fix optimization attribute checks;
remove check for callee_fun->can_throw_non_call_exceptions and
replace it by optimization attribute check; check for flag_exceptions.
* ipa-inline-transform.c (inline_call): Maintain
DECL_FUNCTION_PERSONALITY
* ipa-inline.h (inline_summary): Add contains_cilk_spawn.
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c (revision 221682)
+++ ipa-inline-analysis.c (working copy)
@@ -760,6 +760,31 @@ account_size_time (struct inline_summary
}
}
+/* We proved E to be unreachable, redirect it to __bultin_unreachable. */
+
+static void
+redirect_to_unreachable (struct cgraph_edge *e)
+{
+ struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
+ struct inline_edge_summary *es = inline_edge_summary (e);
+
+ if (e->speculative)
+ e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
+ if (!e->callee)
+ e->make_direct (cgraph_node::get_create
+ (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
+ else
+ e->redirect_callee (cgraph_node::get_create
+ (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
+ e->inline_failed = CIF_UNREACHABLE;
+ e->frequency = 0;
+ e->count = 0;
+ es->call_stmt_size = 0;
+ es->call_stmt_time = 0;
+ if (callee)
+ callee->remove_symbol_and_inline_clones ();
+}
+
/* Set predicate for edge E. */
static void
@@ -769,18 +794,8 @@ edge_set_predicate (struct cgraph_edge *
/* If the edge is determined to be never executed, redirect it
to BUILTIN_UNREACHABLE to save inliner from inlining into it. */
- if (predicate && false_predicate_p (predicate) && e->callee)
- {
- struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
-
- e->redirect_callee (cgraph_node::get_create
- (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
- e->inline_failed = CIF_UNREACHABLE;
- es->call_stmt_size = 0;
- es->call_stmt_time = 0;
- if (callee)
- callee->remove_symbol_and_inline_clones ();
- }
+ if (predicate && false_predicate_p (predicate))
+ redirect_to_unreachable (e);
if (predicate && !true_predicate_p (predicate))
{
if (!es->predicate)
@@ -1228,10 +1243,7 @@ inline_summary_t::duplicate (cgraph_node
info);
if (false_predicate_p (&new_predicate)
&& !false_predicate_p (es->predicate))
- {
- optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
- edge->frequency = 0;
- }
+ optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
edge_set_predicate (edge, &new_predicate);
}
@@ -1250,10 +1262,7 @@ inline_summary_t::duplicate (cgraph_node
info);
if (false_predicate_p (&new_predicate)
&& !false_predicate_p (es->predicate))
- {
- optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
- edge->frequency = 0;
- }
+ optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
edge_set_predicate (edge, &new_predicate);
}
remap_hint_predicate_after_duplication (&info->loop_iterations,
@@ -1441,6 +1450,8 @@ dump_inline_summary (FILE *f, struct cgr
fprintf (f, " always_inline");
if (s->inlinable)
fprintf (f, " inlinable");
+ if (s->contains_cilk_spawn)
+ fprintf (f, " contains_cilk_spawn");
fprintf (f, "\n self time: %i\n", s->self_time);
fprintf (f, " global time: %i\n", s->time);
fprintf (f, " self size: %i\n", s->self_size);
@@ -2925,6 +2936,8 @@ compute_inline_parameters (struct cgraph
else
info->inlinable = tree_inlinable_function_p (node->decl);
+ info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun);
+
/* Type attributes can use parameter indices to describe them. */
if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
node->local.can_change_signature = false;
@@ -3487,14 +3500,6 @@ remap_edge_summaries (struct cgraph_edge
es->predicate, operand_map, offset_map,
possible_truths, toplev_predicate);
edge_set_predicate (e, &p);
- /* TODO: We should remove the edge for code that will be
- optimized out, but we need to keep verifiers and tree-inline
- happy. Make it cold for now. */
- if (false_predicate_p (&p))
- {
- e->count = 0;
- e->frequency = 0;
- }
}
else
edge_set_predicate (e, toplev_predicate);
@@ -3516,14 +3521,6 @@ remap_edge_summaries (struct cgraph_edge
es->predicate, operand_map, offset_map,
possible_truths, toplev_predicate);
edge_set_predicate (e, &p);
- /* TODO: We should remove the edge for code that will be optimized
- out, but we need to keep verifiers and tree-inline happy.
- Make it cold for now. */
- if (false_predicate_p (&p))
- {
- e->count = 0;
- e->frequency = 0;
- }
}
else
edge_set_predicate (e, toplev_predicate);
@@ -4228,6 +4225,7 @@ inline_read_section (struct lto_file_dec
bp = streamer_read_bitpack (&ib);
info->inlinable = bp_unpack_value (&bp, 1);
+ info->contains_cilk_spawn = bp_unpack_value (&bp, 1);
count2 = streamer_read_uhwi (&ib);
gcc_assert (!info->conds);
@@ -4393,6 +4391,7 @@ inline_write_summary (void)
streamer_write_hwi (ob, info->self_time);
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, info->inlinable, 1);
+ bp_pack_value (&bp, info->contains_cilk_spawn, 1);
streamer_write_bitpack (&bp);
streamer_write_uhwi (ob, vec_safe_length (info->conds));
for (i = 0; vec_safe_iterate (info->conds, i, &c); i++)
Index: ipa-inline-transform.c
===================================================================
--- ipa-inline-transform.c (revision 221682)
+++ ipa-inline-transform.c (working copy)
@@ -322,6 +322,10 @@ inline_call (struct cgraph_edge *e, bool
if (to->global.inlined_to)
to = to->global.inlined_to;
+ if (DECL_FUNCTION_PERSONALITY (callee->decl))
+ DECL_FUNCTION_PERSONALITY (to->decl)
+ = DECL_FUNCTION_PERSONALITY (callee->decl);
+
/* If aliases are involved, redirect edge to the actual destination and
possibly remove the aliases. */
if (e->callee != callee)
Index: ipa-inline.h
===================================================================
--- ipa-inline.h (revision 221682)
+++ ipa-inline.h (working copy)
@@ -126,6 +126,9 @@ struct GTY(()) inline_summary
/* False when there something makes inlining impossible (such as va_arg). */
unsigned inlinable : 1;
+ /* True when function contains cilk spawn (and thus we can not inline
+ into it). */
+ unsigned contains_cilk_spawn : 1;
/* Information about function that will result after applying all the
inline decisions present in the callgraph. Generally kept up to
Index: ipa-inline.c
===================================================================
--- ipa-inline.c (revision 221682)
+++ ipa-inline.c (working copy)
@@ -329,8 +329,6 @@ can_inline_edge_p (struct cgraph_edge *e
tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (caller->decl);
tree callee_tree
= callee ? DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee->decl) : NULL;
- struct function *caller_fun = caller->get_fun ();
- struct function *callee_fun = callee ? callee->get_fun () : NULL;
if (!callee->definition)
{
@@ -342,12 +340,6 @@ can_inline_edge_p (struct cgraph_edge *e
e->inline_failed = CIF_USES_COMDAT_LOCAL;
inlinable = false;
}
- else if (!inline_summaries->get (callee)->inlinable
- || (caller_fun && fn_contains_cilk_spawn_p (caller_fun)))
- {
- e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
- inlinable = false;
- }
else if (avail <= AVAIL_INTERPOSABLE)
{
e->inline_failed = CIF_OVERWRITABLE;
@@ -375,16 +367,6 @@ can_inline_edge_p (struct cgraph_edge *e
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.
- Move the flag into cgraph node or mirror it in the inline summary. */
- else if (callee_fun && callee_fun->can_throw_non_call_exceptions
- && !(caller_fun && caller_fun->can_throw_non_call_exceptions))
- {
- e->inline_failed = CIF_NON_CALL_EXCEPTIONS;
- inlinable = false;
- }
/* Check compatibility of target optimization options. */
else if (!targetm.target_option.can_inline_p (caller->decl,
callee->decl))
@@ -392,6 +374,16 @@ can_inline_edge_p (struct cgraph_edge *e
e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
inlinable = false;
}
+ else if (!inline_summaries->get (callee)->inlinable)
+ {
+ e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
+ inlinable = false;
+ }
+ else if (inline_summaries->get (caller)->contains_cilk_spawn)
+ {
+ e->inline_failed = CIF_CILK_SPAWN;
+ inlinable = false;
+ }
/* Don't inline a function with mismatched sanitization attributes. */
else if (!sanitize_attrs_match_for_inline_p (caller->decl, callee->decl))
{
@@ -416,38 +408,52 @@ can_inline_edge_p (struct cgraph_edge *e
/* Strictly speaking only when the callee contains signed integer
math where overflow is undefined. */
if ((opt_for_fn (caller->decl, flag_strict_overflow)
- != opt_for_fn (caller->decl, flag_strict_overflow))
+ != opt_for_fn (callee->decl, flag_strict_overflow))
|| (opt_for_fn (caller->decl, flag_wrapv)
- != opt_for_fn (caller->decl, flag_wrapv))
+ != opt_for_fn (callee->decl, flag_wrapv))
|| (opt_for_fn (caller->decl, flag_trapv)
- != opt_for_fn (caller->decl, flag_trapv))
+ != opt_for_fn (callee->decl, flag_trapv))
/* Strictly speaking only when the callee contains memory
accesses that are not using alias-set zero anyway. */
|| (opt_for_fn (caller->decl, flag_strict_aliasing)
- != opt_for_fn (caller->decl, flag_strict_aliasing))
+ != opt_for_fn (callee->decl, flag_strict_aliasing))
/* Strictly speaking only when the callee uses FP math. */
|| (opt_for_fn (caller->decl, flag_rounding_math)
- != opt_for_fn (caller->decl, flag_rounding_math))
+ != opt_for_fn (callee->decl, flag_rounding_math))
|| (opt_for_fn (caller->decl, flag_trapping_math)
- != opt_for_fn (caller->decl, flag_trapping_math))
+ != opt_for_fn (callee->decl, flag_trapping_math))
|| (opt_for_fn (caller->decl, flag_unsafe_math_optimizations)
- != opt_for_fn (caller->decl, flag_unsafe_math_optimizations))
+ != opt_for_fn (callee->decl, flag_unsafe_math_optimizations))
|| (opt_for_fn (caller->decl, flag_finite_math_only)
- != opt_for_fn (caller->decl, flag_finite_math_only))
+ != opt_for_fn (callee->decl, flag_finite_math_only))
|| (opt_for_fn (caller->decl, flag_signaling_nans)
- != opt_for_fn (caller->decl, flag_signaling_nans))
+ != opt_for_fn (callee->decl, flag_signaling_nans))
|| (opt_for_fn (caller->decl, flag_cx_limited_range)
- != opt_for_fn (caller->decl, flag_cx_limited_range))
+ != opt_for_fn (callee->decl, flag_cx_limited_range))
|| (opt_for_fn (caller->decl, flag_signed_zeros)
- != opt_for_fn (caller->decl, flag_signed_zeros))
+ != opt_for_fn (callee->decl, flag_signed_zeros))
|| (opt_for_fn (caller->decl, flag_associative_math)
- != opt_for_fn (caller->decl, flag_associative_math))
+ != opt_for_fn (callee->decl, flag_associative_math))
|| (opt_for_fn (caller->decl, flag_reciprocal_math)
- != opt_for_fn (caller->decl, flag_reciprocal_math))
+ != opt_for_fn (callee->decl, flag_reciprocal_math))
+ /* We do not want to make code compiled with exceptions to be brought
+ into a non-EH function unless we know that the callee does not
+ throw. This is tracked by DECL_FUNCTION_PERSONALITY. */
+ || (opt_for_fn (caller->decl, flag_non_call_exceptions)
+ != opt_for_fn (callee->decl, flag_non_call_exceptions)
+ /* TODO: We also may allow bringing !flag_non_call_exceptions
+ to flag_non_call_exceptions function, but that may need
+ extra work in tree-inline to add the extra EH edges. */
+ && (!opt_for_fn (callee->decl, flag_non_call_exceptions)
+ || DECL_FUNCTION_PERSONALITY (callee->decl)))
+ || (opt_for_fn (caller->decl, flag_exceptions)
+ != opt_for_fn (callee->decl, flag_exceptions)
+ && (!opt_for_fn (callee->decl, flag_exceptions)
+ || DECL_FUNCTION_PERSONALITY (callee->decl)))
/* Strictly speaking only when the callee contains function
calls that may end up setting errno. */
|| (opt_for_fn (caller->decl, flag_errno_math)
- != opt_for_fn (caller->decl, flag_errno_math))
+ != opt_for_fn (callee->decl, flag_errno_math))
/* When devirtualization is diabled for callee, it is not safe
to inline it as we possibly mangled the type info.
Allow early inlining of always inlines. */
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Fix can_inline_edge_p and code marking calls unreachable
2015-03-26 18:32 Fix can_inline_edge_p and code marking calls unreachable Jan Hubicka
@ 2015-03-26 21:12 ` Jan Hubicka
2015-03-26 22:58 ` Christophe Lyon
0 siblings, 1 reply; 8+ messages in thread
From: Jan Hubicka @ 2015-03-26 21:12 UTC (permalink / raw)
To: Jan Hubicka; +Cc: gcc-patches
Hi,
this patch missed hunk adding CIF code that I commited now
* cif-code.def (CILK_SPAWN): New code.
--- trunk/gcc/cif-code.def 2015/03/26 20:37:53 221709
+++ trunk/gcc/cif-code.def 2015/03/26 21:10:28 221710
@@ -124,6 +124,10 @@
DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
N_("function attribute mismatch"))
+/* We can't inline because of mismatched caller/callee attributes. */
+DEFCIFCODE(CILK_SPAWN, CIF_FINAL_ERROR,
+ N_("caller function contains cilk spawn"))
+
/* We proved that the call is unreachable. */
DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
N_("unreachable"))
I also noticed that this breaks one testcase which is cured by the following patch
I am testing and will commit once it concludes. I apologize for the breakage.
Honza
* ipa-inline.c (check_maybe_up, check_maybe_down, check_match):
New macros.
(can_inline_edge_p): Relax option matching for always inline functions.
Index: ipa-inline.c
===================================================================
--- ipa-inline.c (revision 221706)
+++ ipa-inline.c (working copy)
@@ -298,6 +298,27 @@ sanitize_attrs_match_for_inline_p (const
DECL_ATTRIBUTES (callee));
}
+/* Used for flags where it is safe to inline when caller's value is
+ grater than callee's. */
+#define check_maybe_up(flag) \
+ (opts_for_fn (caller->decl)->x_##flag \
+ != opts_for_fn (callee->decl)->x_##flag \
+ && (!always_inline \
+ || opts_for_fn (caller->decl)->x_##flag \
+ < opts_for_fn (callee->decl)->x_##flag))
+/* Used for flags where it is safe to inline when caller's value is
+ smaller than callee's. */
+#define check_maybe_down(flag) \
+ (opts_for_fn (caller->decl)->x_##flag \
+ != opts_for_fn (callee->decl)->x_##flag \
+ && (!always_inline \
+ || opts_for_fn (caller->decl)->x_##flag \
+ > opts_for_fn (callee->decl)->x_##flag))
+/* Used for flags where exact match is needed for correctness. */
+#define check_match(flag) \
+ (opts_for_fn (caller->decl)->x_##flag \
+ != opts_for_fn (callee->decl)->x_##flag)
+
/* Decide if we can inline the edge and possibly update
inline_failed reason.
We check whether inlining is possible at all and whether
@@ -401,74 +422,60 @@ can_inline_edge_p (struct cgraph_edge *e
optimization attribute. */
else if (caller_tree != callee_tree)
{
+ bool always_inline =
+ (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
+ && lookup_attribute ("always_inline",
+ DECL_ATTRIBUTES (callee->decl)));
+
/* There are some options that change IL semantics which means
we cannot inline in these cases for correctness reason.
Not even for always_inline declared functions. */
/* Strictly speaking only when the callee contains signed integer
math where overflow is undefined. */
- if ((opt_for_fn (caller->decl, flag_strict_overflow)
- != opt_for_fn (callee->decl, flag_strict_overflow))
- || (opt_for_fn (caller->decl, flag_wrapv)
- != opt_for_fn (callee->decl, flag_wrapv))
- || (opt_for_fn (caller->decl, flag_trapv)
- != opt_for_fn (callee->decl, flag_trapv))
+ if ((check_maybe_up (flag_strict_overflow)
+ /* this flag is set by optimize. Allow inlining across
+ optimize boundary. */
+ && (!opt_for_fn (caller->decl, optimize)
+ == !opt_for_fn (callee->decl, optimize) || !always_inline))
+ || check_match (flag_wrapv)
+ || check_match (flag_trapv)
/* Strictly speaking only when the callee contains memory
accesses that are not using alias-set zero anyway. */
- || (opt_for_fn (caller->decl, flag_strict_aliasing)
- != opt_for_fn (callee->decl, flag_strict_aliasing))
+ || check_maybe_down (flag_strict_aliasing)
/* Strictly speaking only when the callee uses FP math. */
- || (opt_for_fn (caller->decl, flag_rounding_math)
- != opt_for_fn (callee->decl, flag_rounding_math))
- || (opt_for_fn (caller->decl, flag_trapping_math)
- != opt_for_fn (callee->decl, flag_trapping_math))
- || (opt_for_fn (caller->decl, flag_unsafe_math_optimizations)
- != opt_for_fn (callee->decl, flag_unsafe_math_optimizations))
- || (opt_for_fn (caller->decl, flag_finite_math_only)
- != opt_for_fn (callee->decl, flag_finite_math_only))
- || (opt_for_fn (caller->decl, flag_signaling_nans)
- != opt_for_fn (callee->decl, flag_signaling_nans))
- || (opt_for_fn (caller->decl, flag_cx_limited_range)
- != opt_for_fn (callee->decl, flag_cx_limited_range))
- || (opt_for_fn (caller->decl, flag_signed_zeros)
- != opt_for_fn (callee->decl, flag_signed_zeros))
- || (opt_for_fn (caller->decl, flag_associative_math)
- != opt_for_fn (callee->decl, flag_associative_math))
- || (opt_for_fn (caller->decl, flag_reciprocal_math)
- != opt_for_fn (callee->decl, flag_reciprocal_math))
+ || check_maybe_up (flag_rounding_math)
+ || check_maybe_up (flag_trapping_math)
+ || check_maybe_down (flag_unsafe_math_optimizations)
+ || check_maybe_down (flag_finite_math_only)
+ || check_maybe_up (flag_signaling_nans)
+ || check_maybe_down (flag_cx_limited_range)
+ || check_maybe_up (flag_signed_zeros)
+ || check_maybe_down (flag_associative_math)
+ || check_maybe_down (flag_reciprocal_math)
/* We do not want to make code compiled with exceptions to be brought
into a non-EH function unless we know that the callee does not
throw. This is tracked by DECL_FUNCTION_PERSONALITY. */
- || (opt_for_fn (caller->decl, flag_non_call_exceptions)
- != opt_for_fn (callee->decl, flag_non_call_exceptions)
+ || (check_match (flag_non_call_exceptions)
/* TODO: We also may allow bringing !flag_non_call_exceptions
to flag_non_call_exceptions function, but that may need
extra work in tree-inline to add the extra EH edges. */
&& (!opt_for_fn (callee->decl, flag_non_call_exceptions)
|| DECL_FUNCTION_PERSONALITY (callee->decl)))
- || (!opt_for_fn (caller->decl, flag_exceptions)
- && opt_for_fn (callee->decl, flag_exceptions)
+ || (check_maybe_up (flag_exceptions)
&& DECL_FUNCTION_PERSONALITY (callee->decl))
/* Strictly speaking only when the callee contains function
calls that may end up setting errno. */
- || (opt_for_fn (caller->decl, flag_errno_math)
- != opt_for_fn (callee->decl, flag_errno_math))
+ || check_maybe_up (flag_errno_math)
/* When devirtualization is diabled for callee, it is not safe
to inline it as we possibly mangled the type info.
Allow early inlining of always inlines. */
- || (opt_for_fn (caller->decl, flag_devirtualize)
- && !opt_for_fn (callee->decl, flag_devirtualize)
- && (!early
- || (!DECL_DISREGARD_INLINE_LIMITS (callee->decl)
- || !lookup_attribute ("always_inline",
- DECL_ATTRIBUTES (callee->decl))))))
+ || (!early && check_maybe_down (flag_devirtualize)))
{
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
inlinable = false;
}
/* gcc.dg/pr43564.c. Apply user-forced inline even at -O0. */
- else if (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
- && lookup_attribute ("always_inline",
- DECL_ATTRIBUTES (callee->decl)))
+ else if (always_inline)
;
/* When user added an attribute to the callee honor it. */
else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Fix can_inline_edge_p and code marking calls unreachable
2015-03-26 21:12 ` Jan Hubicka
@ 2015-03-26 22:58 ` Christophe Lyon
2015-03-26 23:47 ` Jan Hubicka
0 siblings, 1 reply; 8+ messages in thread
From: Christophe Lyon @ 2015-03-26 22:58 UTC (permalink / raw)
To: Jan Hubicka; +Cc: gcc-patches
On 26 March 2015 at 22:12, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this patch missed hunk adding CIF code that I commited now
> * cif-code.def (CILK_SPAWN): New code
Hi,
After this fix, I can see build failures in glibc:
key_call.c:574:1: internal compiler error: in inline_call, at
ipa-inline-transform.c:386
}
^
0x10eb475 inline_call(cgraph_edge*, bool, vec<cgraph_edge*, va_heap,
vl_ptr>*, int*, bool, bool*)
/tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline-transform.c:381
0x10e43ed inline_small_functions
/tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline.c:1942
0x10e4ead ipa_inline
/tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline.c:2345
See http://abe.tcwglab.linaro.org/logs/validations/cross-validation/gcc-build/trunk/221710/build.html
for more detailed logs.
Thanks
Christophe
>
> --- trunk/gcc/cif-code.def 2015/03/26 20:37:53 221709
> +++ trunk/gcc/cif-code.def 2015/03/26 21:10:28 221710
> @@ -124,6 +124,10 @@
> DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
> N_("function attribute mismatch"))
>
> +/* We can't inline because of mismatched caller/callee attributes. */
> +DEFCIFCODE(CILK_SPAWN, CIF_FINAL_ERROR,
> + N_("caller function contains cilk spawn"))
> +
> /* We proved that the call is unreachable. */
> DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
> N_("unreachable"))
>
> I also noticed that this breaks one testcase which is cured by the following patch
> I am testing and will commit once it concludes. I apologize for the breakage.
>
> Honza
>
> * ipa-inline.c (check_maybe_up, check_maybe_down, check_match):
> New macros.
> (can_inline_edge_p): Relax option matching for always inline functions.
> Index: ipa-inline.c
> ===================================================================
> --- ipa-inline.c (revision 221706)
> +++ ipa-inline.c (working copy)
> @@ -298,6 +298,27 @@ sanitize_attrs_match_for_inline_p (const
> DECL_ATTRIBUTES (callee));
> }
>
> +/* Used for flags where it is safe to inline when caller's value is
> + grater than callee's. */
> +#define check_maybe_up(flag) \
> + (opts_for_fn (caller->decl)->x_##flag \
> + != opts_for_fn (callee->decl)->x_##flag \
> + && (!always_inline \
> + || opts_for_fn (caller->decl)->x_##flag \
> + < opts_for_fn (callee->decl)->x_##flag))
> +/* Used for flags where it is safe to inline when caller's value is
> + smaller than callee's. */
> +#define check_maybe_down(flag) \
> + (opts_for_fn (caller->decl)->x_##flag \
> + != opts_for_fn (callee->decl)->x_##flag \
> + && (!always_inline \
> + || opts_for_fn (caller->decl)->x_##flag \
> + > opts_for_fn (callee->decl)->x_##flag))
> +/* Used for flags where exact match is needed for correctness. */
> +#define check_match(flag) \
> + (opts_for_fn (caller->decl)->x_##flag \
> + != opts_for_fn (callee->decl)->x_##flag)
> +
> /* Decide if we can inline the edge and possibly update
> inline_failed reason.
> We check whether inlining is possible at all and whether
> @@ -401,74 +422,60 @@ can_inline_edge_p (struct cgraph_edge *e
> optimization attribute. */
> else if (caller_tree != callee_tree)
> {
> + bool always_inline =
> + (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
> + && lookup_attribute ("always_inline",
> + DECL_ATTRIBUTES (callee->decl)));
> +
> /* There are some options that change IL semantics which means
> we cannot inline in these cases for correctness reason.
> Not even for always_inline declared functions. */
> /* Strictly speaking only when the callee contains signed integer
> math where overflow is undefined. */
> - if ((opt_for_fn (caller->decl, flag_strict_overflow)
> - != opt_for_fn (callee->decl, flag_strict_overflow))
> - || (opt_for_fn (caller->decl, flag_wrapv)
> - != opt_for_fn (callee->decl, flag_wrapv))
> - || (opt_for_fn (caller->decl, flag_trapv)
> - != opt_for_fn (callee->decl, flag_trapv))
> + if ((check_maybe_up (flag_strict_overflow)
> + /* this flag is set by optimize. Allow inlining across
> + optimize boundary. */
> + && (!opt_for_fn (caller->decl, optimize)
> + == !opt_for_fn (callee->decl, optimize) || !always_inline))
> + || check_match (flag_wrapv)
> + || check_match (flag_trapv)
> /* Strictly speaking only when the callee contains memory
> accesses that are not using alias-set zero anyway. */
> - || (opt_for_fn (caller->decl, flag_strict_aliasing)
> - != opt_for_fn (callee->decl, flag_strict_aliasing))
> + || check_maybe_down (flag_strict_aliasing)
> /* Strictly speaking only when the callee uses FP math. */
> - || (opt_for_fn (caller->decl, flag_rounding_math)
> - != opt_for_fn (callee->decl, flag_rounding_math))
> - || (opt_for_fn (caller->decl, flag_trapping_math)
> - != opt_for_fn (callee->decl, flag_trapping_math))
> - || (opt_for_fn (caller->decl, flag_unsafe_math_optimizations)
> - != opt_for_fn (callee->decl, flag_unsafe_math_optimizations))
> - || (opt_for_fn (caller->decl, flag_finite_math_only)
> - != opt_for_fn (callee->decl, flag_finite_math_only))
> - || (opt_for_fn (caller->decl, flag_signaling_nans)
> - != opt_for_fn (callee->decl, flag_signaling_nans))
> - || (opt_for_fn (caller->decl, flag_cx_limited_range)
> - != opt_for_fn (callee->decl, flag_cx_limited_range))
> - || (opt_for_fn (caller->decl, flag_signed_zeros)
> - != opt_for_fn (callee->decl, flag_signed_zeros))
> - || (opt_for_fn (caller->decl, flag_associative_math)
> - != opt_for_fn (callee->decl, flag_associative_math))
> - || (opt_for_fn (caller->decl, flag_reciprocal_math)
> - != opt_for_fn (callee->decl, flag_reciprocal_math))
> + || check_maybe_up (flag_rounding_math)
> + || check_maybe_up (flag_trapping_math)
> + || check_maybe_down (flag_unsafe_math_optimizations)
> + || check_maybe_down (flag_finite_math_only)
> + || check_maybe_up (flag_signaling_nans)
> + || check_maybe_down (flag_cx_limited_range)
> + || check_maybe_up (flag_signed_zeros)
> + || check_maybe_down (flag_associative_math)
> + || check_maybe_down (flag_reciprocal_math)
> /* We do not want to make code compiled with exceptions to be brought
> into a non-EH function unless we know that the callee does not
> throw. This is tracked by DECL_FUNCTION_PERSONALITY. */
> - || (opt_for_fn (caller->decl, flag_non_call_exceptions)
> - != opt_for_fn (callee->decl, flag_non_call_exceptions)
> + || (check_match (flag_non_call_exceptions)
> /* TODO: We also may allow bringing !flag_non_call_exceptions
> to flag_non_call_exceptions function, but that may need
> extra work in tree-inline to add the extra EH edges. */
> && (!opt_for_fn (callee->decl, flag_non_call_exceptions)
> || DECL_FUNCTION_PERSONALITY (callee->decl)))
> - || (!opt_for_fn (caller->decl, flag_exceptions)
> - && opt_for_fn (callee->decl, flag_exceptions)
> + || (check_maybe_up (flag_exceptions)
> && DECL_FUNCTION_PERSONALITY (callee->decl))
> /* Strictly speaking only when the callee contains function
> calls that may end up setting errno. */
> - || (opt_for_fn (caller->decl, flag_errno_math)
> - != opt_for_fn (callee->decl, flag_errno_math))
> + || check_maybe_up (flag_errno_math)
> /* When devirtualization is diabled for callee, it is not safe
> to inline it as we possibly mangled the type info.
> Allow early inlining of always inlines. */
> - || (opt_for_fn (caller->decl, flag_devirtualize)
> - && !opt_for_fn (callee->decl, flag_devirtualize)
> - && (!early
> - || (!DECL_DISREGARD_INLINE_LIMITS (callee->decl)
> - || !lookup_attribute ("always_inline",
> - DECL_ATTRIBUTES (callee->decl))))))
> + || (!early && check_maybe_down (flag_devirtualize)))
> {
> e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
> inlinable = false;
> }
> /* gcc.dg/pr43564.c. Apply user-forced inline even at -O0. */
> - else if (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
> - && lookup_attribute ("always_inline",
> - DECL_ATTRIBUTES (callee->decl)))
> + else if (always_inline)
> ;
> /* When user added an attribute to the callee honor it. */
> else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Fix can_inline_edge_p and code marking calls unreachable
2015-03-26 22:58 ` Christophe Lyon
@ 2015-03-26 23:47 ` Jan Hubicka
2015-03-27 2:05 ` Jan Hubicka
2015-03-27 2:09 ` Markus Trippelsdorf
0 siblings, 2 replies; 8+ messages in thread
From: Jan Hubicka @ 2015-03-26 23:47 UTC (permalink / raw)
To: Christophe Lyon; +Cc: Jan Hubicka, gcc-patches
> On 26 March 2015 at 22:12, Jan Hubicka <hubicka@ucw.cz> wrote:
> > Hi,
> > this patch missed hunk adding CIF code that I commited now
> > * cif-code.def (CILK_SPAWN): New code
>
> Hi,
> After this fix, I can see build failures in glibc:
> key_call.c:574:1: internal compiler error: in inline_call, at
> ipa-inline-transform.c:386
> }
> ^
> 0x10eb475 inline_call(cgraph_edge*, bool, vec<cgraph_edge*, va_heap,
> vl_ptr>*, int*, bool, bool*)
> /tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline-transform.c:381
> 0x10e43ed inline_small_functions
> /tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline.c:1942
> 0x10e4ead ipa_inline
> /tmp/9065933_3.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/ipa-inline.c:2345
>
> See http://abe.tcwglab.linaro.org/logs/validations/cross-validation/gcc-build/trunk/221710/build.html
> for more detailed logs.
Can you please send me preprocessed testcase? It is probably another misaccounting
bug in ipa-inline-analysis. I may just silence this assert for this stage 4.
Honza
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Fix can_inline_edge_p and code marking calls unreachable
2015-03-26 23:47 ` Jan Hubicka
@ 2015-03-27 2:05 ` Jan Hubicka
2015-03-27 2:09 ` Markus Trippelsdorf
1 sibling, 0 replies; 8+ messages in thread
From: Jan Hubicka @ 2015-03-27 2:05 UTC (permalink / raw)
To: Jan Hubicka; +Cc: Christophe Lyon, gcc-patches
Hi,
I reproduced the problem of Firefox LTO (though small testcase would be welcome)
The problem is in a way we walk edges that now can be turned from indirect to direct.
I am working on a fix.
Honza
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Fix can_inline_edge_p and code marking calls unreachable
2015-03-26 23:47 ` Jan Hubicka
2015-03-27 2:05 ` Jan Hubicka
@ 2015-03-27 2:09 ` Markus Trippelsdorf
2015-03-27 2:14 ` Jan Hubicka
1 sibling, 1 reply; 8+ messages in thread
From: Markus Trippelsdorf @ 2015-03-27 2:09 UTC (permalink / raw)
To: Jan Hubicka; +Cc: Christophe Lyon, gcc-patches
On 2015.03.27 at 00:46 +0100, Jan Hubicka wrote:
> > On 26 March 2015 at 22:12, Jan Hubicka <hubicka@ucw.cz> wrote:
> > After this fix, I can see build failures in glibc:
> > key_call.c:574:1: internal compiler error: in inline_call, at
> > ipa-inline-transform.c:386
>
> Can you please send me preprocessed testcase? It is probably another misaccounting
> bug in ipa-inline-analysis. I may just silence this assert for this stage 4.
Also happens when building the Linux kernel:
trippels@gcc2-power8 linux-3.18.8 % cat nf_sockopt.i
int a;
int (*b)(), (*c)();
int fn1(int p1) {
if (a)
return 0;
if (p1) {
c();
b();
}
}
void fn2() { fn1(0); }
trippels@gcc2-power8 linux-3.18.8 % /home/trippels/gcc_test/usr/local/bin/gcc -O2 -c nf_sockopt.i
nf_sockopt.i:11:1: internal compiler error: in inline_call, at ipa-inline-transform.c:386
void fn2() { fn1(0); }
^
0x10e435cf inline_call(cgraph_edge*, bool, vec<cgraph_edge*, va_heap, vl_ptr>*, int*, bool, bool*)
../../gcc/gcc/ipa-inline-transform.c:381
0x10e39a7b inline_small_functions
../../gcc/gcc/ipa-inline.c:1949
0x10e39a7b ipa_inline
../../gcc/gcc/ipa-inline.c:2352
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
--
Markus
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Fix can_inline_edge_p and code marking calls unreachable
2015-03-27 2:09 ` Markus Trippelsdorf
@ 2015-03-27 2:14 ` Jan Hubicka
2015-03-27 9:36 ` Christophe Lyon
0 siblings, 1 reply; 8+ messages in thread
From: Jan Hubicka @ 2015-03-27 2:14 UTC (permalink / raw)
To: Markus Trippelsdorf; +Cc: Jan Hubicka, Christophe Lyon, gcc-patches
> On 2015.03.27 at 00:46 +0100, Jan Hubicka wrote:
> > > On 26 March 2015 at 22:12, Jan Hubicka <hubicka@ucw.cz> wrote:
> > > After this fix, I can see build failures in glibc:
> > > key_call.c:574:1: internal compiler error: in inline_call, at
> > > ipa-inline-transform.c:386
> >
> > Can you please send me preprocessed testcase? It is probably another misaccounting
> > bug in ipa-inline-analysis. I may just silence this assert for this stage 4.
>
> Also happens when building the Linux kernel:
>
> trippels@gcc2-power8 linux-3.18.8 % cat nf_sockopt.i
> int a;
> int (*b)(), (*c)();
> int fn1(int p1) {
> if (a)
> return 0;
> if (p1) {
> c();
> b();
> }
> }
> void fn2() { fn1(0); }
Great, Markus, having a testcase is important for covering this code path.
I am attaching a fix, will test it with your testcase and commit.
* ipa-inline-analysis.c (redirect_to_unreachable): Be prepared for
edge to change by speculation resolution or redirection.
(edge_set_predicate): Likewise.
(inline_summary_t::duplicate): Likewise.
(remap_edge_summaries): Likewise.
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c (revision 221706)
+++ ipa-inline-analysis.c (working copy)
@@ -762,20 +762,20 @@ account_size_time (struct inline_summary
/* We proved E to be unreachable, redirect it to __bultin_unreachable. */
-static void
+static struct cgraph_edge *
redirect_to_unreachable (struct cgraph_edge *e)
{
struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
- struct inline_edge_summary *es = inline_edge_summary (e);
if (e->speculative)
- e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
- if (!e->callee)
+ e = e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
+ else if (!e->callee)
e->make_direct (cgraph_node::get_create
(builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
else
e->redirect_callee (cgraph_node::get_create
(builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
+ struct inline_edge_summary *es = inline_edge_summary (e);
e->inline_failed = CIF_UNREACHABLE;
e->frequency = 0;
e->count = 0;
@@ -783,6 +783,7 @@ redirect_to_unreachable (struct cgraph_e
es->call_stmt_time = 0;
if (callee)
callee->remove_symbol_and_inline_clones ();
+ return e;
}
/* Set predicate for edge E. */
@@ -790,12 +791,12 @@ redirect_to_unreachable (struct cgraph_e
static void
edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate)
{
- struct inline_edge_summary *es = inline_edge_summary (e);
-
/* If the edge is determined to be never executed, redirect it
to BUILTIN_UNREACHABLE to save inliner from inlining into it. */
if (predicate && false_predicate_p (predicate))
- redirect_to_unreachable (e);
+ e = redirect_to_unreachable (e);
+
+ struct inline_edge_summary *es = inline_edge_summary (e);
if (predicate && !true_predicate_p (predicate))
{
if (!es->predicate)
@@ -1184,7 +1185,7 @@ inline_summary_t::duplicate (cgraph_node
size_time_entry *e;
int optimized_out_size = 0;
bool inlined_to_p = false;
- struct cgraph_edge *edge;
+ struct cgraph_edge *edge, *next;
info->entry = 0;
known_vals.safe_grow_cleared (count);
@@ -1229,10 +1230,11 @@ inline_summary_t::duplicate (cgraph_node
/* Remap edge predicates with the same simplification as above.
Also copy constantness arrays. */
- for (edge = dst->callees; edge; edge = edge->next_callee)
+ for (edge = dst->callees; edge; edge = next)
{
struct predicate new_predicate;
struct inline_edge_summary *es = inline_edge_summary (edge);
+ next = edge->next_callee;
if (!edge->inline_failed)
inlined_to_p = true;
@@ -1249,10 +1251,11 @@ inline_summary_t::duplicate (cgraph_node
/* Remap indirect edge predicates with the same simplificaiton as above.
Also copy constantness arrays. */
- for (edge = dst->indirect_calls; edge; edge = edge->next_callee)
+ for (edge = dst->indirect_calls; edge; edge = next)
{
struct predicate new_predicate;
struct inline_edge_summary *es = inline_edge_summary (edge);
+ next = edge->next_callee;
gcc_checking_assert (edge->inline_failed);
if (!es->predicate)
@@ -3484,11 +3487,12 @@ remap_edge_summaries (struct cgraph_edge
clause_t possible_truths,
struct predicate *toplev_predicate)
{
- struct cgraph_edge *e;
- for (e = node->callees; e; e = e->next_callee)
+ struct cgraph_edge *e, *next;
+ for (e = node->callees; e; e = next)
{
struct inline_edge_summary *es = inline_edge_summary (e);
struct predicate p;
+ next = e->next_callee;
if (e->inline_failed)
{
@@ -3509,10 +3513,11 @@ remap_edge_summaries (struct cgraph_edge
operand_map, offset_map, possible_truths,
toplev_predicate);
}
- for (e = node->indirect_calls; e; e = e->next_callee)
+ for (e = node->indirect_calls; e; e = next)
{
struct inline_edge_summary *es = inline_edge_summary (e);
struct predicate p;
+ next = e->next_callee;
remap_edge_change_prob (inlined_edge, e);
if (es->predicate)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Fix can_inline_edge_p and code marking calls unreachable
2015-03-27 2:14 ` Jan Hubicka
@ 2015-03-27 9:36 ` Christophe Lyon
0 siblings, 0 replies; 8+ messages in thread
From: Christophe Lyon @ 2015-03-27 9:36 UTC (permalink / raw)
To: Jan Hubicka; +Cc: Markus Trippelsdorf, gcc-patches
On 27 March 2015 at 03:14, Jan Hubicka <hubicka@ucw.cz> wrote:
>> On 2015.03.27 at 00:46 +0100, Jan Hubicka wrote:
>> > > On 26 March 2015 at 22:12, Jan Hubicka <hubicka@ucw.cz> wrote:
>> > > After this fix, I can see build failures in glibc:
>> > > key_call.c:574:1: internal compiler error: in inline_call, at
>> > > ipa-inline-transform.c:386
>> >
>> > Can you please send me preprocessed testcase? It is probably another misaccounting
>> > bug in ipa-inline-analysis. I may just silence this assert for this stage 4.
>>
>> Also happens when building the Linux kernel:
>>
>> trippels@gcc2-power8 linux-3.18.8 % cat nf_sockopt.i
>> int a;
>> int (*b)(), (*c)();
>> int fn1(int p1) {
>> if (a)
>> return 0;
>> if (p1) {
>> c();
>> b();
>> }
>> }
>> void fn2() { fn1(0); }
>
> Great, Markus, having a testcase is important for covering this code path.
> I am attaching a fix, will test it with your testcase and commit.
>
> * ipa-inline-analysis.c (redirect_to_unreachable): Be prepared for
> edge to change by speculation resolution or redirection.
> (edge_set_predicate): Likewise.
> (inline_summary_t::duplicate): Likewise.
> (remap_edge_summaries): Likewise.
This commit (221718) does fix the problems I saw, thanks.
Christophe.
> Index: ipa-inline-analysis.c
> ===================================================================
> --- ipa-inline-analysis.c (revision 221706)
> +++ ipa-inline-analysis.c (working copy)
> @@ -762,20 +762,20 @@ account_size_time (struct inline_summary
>
> /* We proved E to be unreachable, redirect it to __bultin_unreachable. */
>
> -static void
> +static struct cgraph_edge *
> redirect_to_unreachable (struct cgraph_edge *e)
> {
> struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
> - struct inline_edge_summary *es = inline_edge_summary (e);
>
> if (e->speculative)
> - e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
> - if (!e->callee)
> + e = e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
> + else if (!e->callee)
> e->make_direct (cgraph_node::get_create
> (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
> else
> e->redirect_callee (cgraph_node::get_create
> (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
> + struct inline_edge_summary *es = inline_edge_summary (e);
> e->inline_failed = CIF_UNREACHABLE;
> e->frequency = 0;
> e->count = 0;
> @@ -783,6 +783,7 @@ redirect_to_unreachable (struct cgraph_e
> es->call_stmt_time = 0;
> if (callee)
> callee->remove_symbol_and_inline_clones ();
> + return e;
> }
>
> /* Set predicate for edge E. */
> @@ -790,12 +791,12 @@ redirect_to_unreachable (struct cgraph_e
> static void
> edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate)
> {
> - struct inline_edge_summary *es = inline_edge_summary (e);
> -
> /* If the edge is determined to be never executed, redirect it
> to BUILTIN_UNREACHABLE to save inliner from inlining into it. */
> if (predicate && false_predicate_p (predicate))
> - redirect_to_unreachable (e);
> + e = redirect_to_unreachable (e);
> +
> + struct inline_edge_summary *es = inline_edge_summary (e);
> if (predicate && !true_predicate_p (predicate))
> {
> if (!es->predicate)
> @@ -1184,7 +1185,7 @@ inline_summary_t::duplicate (cgraph_node
> size_time_entry *e;
> int optimized_out_size = 0;
> bool inlined_to_p = false;
> - struct cgraph_edge *edge;
> + struct cgraph_edge *edge, *next;
>
> info->entry = 0;
> known_vals.safe_grow_cleared (count);
> @@ -1229,10 +1230,11 @@ inline_summary_t::duplicate (cgraph_node
>
> /* Remap edge predicates with the same simplification as above.
> Also copy constantness arrays. */
> - for (edge = dst->callees; edge; edge = edge->next_callee)
> + for (edge = dst->callees; edge; edge = next)
> {
> struct predicate new_predicate;
> struct inline_edge_summary *es = inline_edge_summary (edge);
> + next = edge->next_callee;
>
> if (!edge->inline_failed)
> inlined_to_p = true;
> @@ -1249,10 +1251,11 @@ inline_summary_t::duplicate (cgraph_node
>
> /* Remap indirect edge predicates with the same simplificaiton as above.
> Also copy constantness arrays. */
> - for (edge = dst->indirect_calls; edge; edge = edge->next_callee)
> + for (edge = dst->indirect_calls; edge; edge = next)
> {
> struct predicate new_predicate;
> struct inline_edge_summary *es = inline_edge_summary (edge);
> + next = edge->next_callee;
>
> gcc_checking_assert (edge->inline_failed);
> if (!es->predicate)
> @@ -3484,11 +3487,12 @@ remap_edge_summaries (struct cgraph_edge
> clause_t possible_truths,
> struct predicate *toplev_predicate)
> {
> - struct cgraph_edge *e;
> - for (e = node->callees; e; e = e->next_callee)
> + struct cgraph_edge *e, *next;
> + for (e = node->callees; e; e = next)
> {
> struct inline_edge_summary *es = inline_edge_summary (e);
> struct predicate p;
> + next = e->next_callee;
>
> if (e->inline_failed)
> {
> @@ -3509,10 +3513,11 @@ remap_edge_summaries (struct cgraph_edge
> operand_map, offset_map, possible_truths,
> toplev_predicate);
> }
> - for (e = node->indirect_calls; e; e = e->next_callee)
> + for (e = node->indirect_calls; e; e = next)
> {
> struct inline_edge_summary *es = inline_edge_summary (e);
> struct predicate p;
> + next = e->next_callee;
>
> remap_edge_change_prob (inlined_edge, e);
> if (es->predicate)
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-03-27 9:36 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-26 18:32 Fix can_inline_edge_p and code marking calls unreachable Jan Hubicka
2015-03-26 21:12 ` Jan Hubicka
2015-03-26 22:58 ` Christophe Lyon
2015-03-26 23:47 ` Jan Hubicka
2015-03-27 2:05 ` Jan Hubicka
2015-03-27 2:09 ` Markus Trippelsdorf
2015-03-27 2:14 ` Jan Hubicka
2015-03-27 9:36 ` Christophe Lyon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).