Commit 128e0d89 by Jan Hubicka Committed by Jan Hubicka

re PR fortran/48636 (Enable more inlining with -O2 and higher)


	PR fortran/48636
	* gcc.dg/ipa/inlinehint-2.c: New testcase.
	* ipa-inline-analysis.c (dump_inline_hints): Dump loop stride.
	(set_hint_predicate): New function.
	(reset_inline_summary): Reset loop stride.
	(remap_predicate_after_duplication): New function.
	(remap_hint_predicate_after_duplication): New function.
	(inline_node_duplication_hook): Update.
	(dump_inline_summary): Dump stride summaries.
	(estimate_function_body_sizes): Compute strides.
	(remap_hint_predicate): New function.
	(inline_merge_summary): Use it.
	(inline_read_section): Read stride.
	(inline_write_summary): Write stride.
	* ipa-inline.c (want_inline_small_function_p): Handle strides.
	(edge_badness): Likewise.
	* ipa-inline.h (inline_hints_vals): Add stride hint.
	(inline_summary): Update stride.

From-SVN: r191232
parent cb261eb7
2012-09-12 Jan Hubicka <jh@suse.cz>
PR fortran/48636
* ipa-inline-analysis.c (dump_inline_hints): Dump loop stride.
(set_hint_predicate): New function.
(reset_inline_summary): Reset loop stride.
(remap_predicate_after_duplication): New function.
(remap_hint_predicate_after_duplication): New function.
(inline_node_duplication_hook): Update.
(dump_inline_summary): Dump stride summaries.
(estimate_function_body_sizes): Compute strides.
(remap_hint_predicate): New function.
(inline_merge_summary): Use it.
(inline_read_section): Read stride.
(inline_write_summary): Write stride.
* ipa-inline.c (want_inline_small_function_p): Handle strides.
(edge_badness): Likewise.
* ipa-inline.h (inline_hints_vals): Add stride hint.
(inline_summary): Update stride.
2012-09-12 Uros Bizjak <ubizjak@gmail.com> 2012-09-12 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.c (x86_prefetch_sse): Change to unsigned char. * config/i386/i386.c (x86_prefetch_sse): Change to unsigned char.
......
...@@ -634,6 +634,11 @@ dump_inline_hints (FILE *f, inline_hints hints) ...@@ -634,6 +634,11 @@ dump_inline_hints (FILE *f, inline_hints hints)
hints &= ~INLINE_HINT_loop_iterations; hints &= ~INLINE_HINT_loop_iterations;
fprintf (f, " loop_iterations"); fprintf (f, " loop_iterations");
} }
if (hints & INLINE_HINT_loop_stride)
{
hints &= ~INLINE_HINT_loop_stride;
fprintf (f, " loop_stride");
}
gcc_assert (!hints); gcc_assert (!hints);
} }
...@@ -719,6 +724,26 @@ edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate) ...@@ -719,6 +724,26 @@ edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate)
} }
} }
/* Set predicate for hint *P. */
static void
set_hint_predicate (struct predicate **p, struct predicate new_predicate)
{
if (false_predicate_p (&new_predicate)
|| true_predicate_p (&new_predicate))
{
if (*p)
pool_free (edge_predicate_pool, *p);
*p = NULL;
}
else
{
if (!*p)
*p = (struct predicate *)pool_alloc (edge_predicate_pool);
**p = new_predicate;
}
}
/* KNOWN_VALS is partial mapping of parameters of NODE to constant values. /* KNOWN_VALS is partial mapping of parameters of NODE to constant values.
KNOWN_AGGS is a vector of aggreggate jump functions for each parameter. KNOWN_AGGS is a vector of aggreggate jump functions for each parameter.
...@@ -953,6 +978,11 @@ reset_inline_summary (struct cgraph_node *node) ...@@ -953,6 +978,11 @@ reset_inline_summary (struct cgraph_node *node)
pool_free (edge_predicate_pool, info->loop_iterations); pool_free (edge_predicate_pool, info->loop_iterations);
info->loop_iterations = NULL; info->loop_iterations = NULL;
} }
if (info->loop_stride)
{
pool_free (edge_predicate_pool, info->loop_stride);
info->loop_stride = NULL;
}
VEC_free (condition, gc, info->conds); VEC_free (condition, gc, info->conds);
VEC_free (size_time_entry,gc, info->entry); VEC_free (size_time_entry,gc, info->entry);
for (e = node->callees; e; e = e->next_callee) for (e = node->callees; e; e = e->next_callee)
...@@ -975,6 +1005,52 @@ inline_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) ...@@ -975,6 +1005,52 @@ inline_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
memset (info, 0, sizeof (inline_summary_t)); memset (info, 0, sizeof (inline_summary_t));
} }
/* Remap predicate P of former function to be predicate of duplicated functoin.
POSSIBLE_TRUTHS is clause of possible truths in the duplicated node,
INFO is inline summary of the duplicated node. */
static struct predicate
remap_predicate_after_duplication (struct predicate *p,
clause_t possible_truths,
struct inline_summary *info)
{
struct predicate new_predicate = true_predicate ();
int j;
for (j = 0; p->clause[j]; j++)
if (!(possible_truths & p->clause[j]))
{
new_predicate = false_predicate ();
break;
}
else
add_clause (info->conds, &new_predicate,
possible_truths & p->clause[j]);
return new_predicate;
}
/* Same as remap_predicate_after_duplication but handle hint predicate *P.
Additionally care about allocating new memory slot for updated predicate
and set it to NULL when it becomes true or false (and thus uninteresting).
*/
static void
remap_hint_predicate_after_duplication (struct predicate **p,
clause_t possible_truths,
struct inline_summary *info)
{
struct predicate new_predicate;
if (!*p)
return;
new_predicate = remap_predicate_after_duplication (*p,
possible_truths,
info);
/* We do not want to free previous predicate; it is used by node origin. */
*p = NULL;
set_hint_predicate (p, new_predicate);
}
/* Hook that is called by cgraph.c when a node is duplicated. */ /* Hook that is called by cgraph.c when a node is duplicated. */
...@@ -1042,16 +1118,10 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -1042,16 +1118,10 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
to be true. */ to be true. */
for (i = 0; VEC_iterate (size_time_entry, entry, i, e); i++) for (i = 0; VEC_iterate (size_time_entry, entry, i, e); i++)
{ {
struct predicate new_predicate = true_predicate (); struct predicate new_predicate;
for (j = 0; e->predicate.clause[j]; j++) new_predicate = remap_predicate_after_duplication (&e->predicate,
if (!(possible_truths & e->predicate.clause[j])) possible_truths,
{ info);
new_predicate = false_predicate ();
break;
}
else
add_clause (info->conds, &new_predicate,
possible_truths & e->predicate.clause[j]);
if (false_predicate_p (&new_predicate)) if (false_predicate_p (&new_predicate))
{ {
optimized_out_size += e->size; optimized_out_size += e->size;
...@@ -1065,22 +1135,16 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -1065,22 +1135,16 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
Also copy constantness arrays. */ Also copy constantness arrays. */
for (edge = dst->callees; edge; edge = edge->next_callee) for (edge = dst->callees; edge; edge = edge->next_callee)
{ {
struct predicate new_predicate = true_predicate (); struct predicate new_predicate;
struct inline_edge_summary *es = inline_edge_summary (edge); struct inline_edge_summary *es = inline_edge_summary (edge);
if (!edge->inline_failed) if (!edge->inline_failed)
inlined_to_p = true; inlined_to_p = true;
if (!es->predicate) if (!es->predicate)
continue; continue;
for (j = 0; es->predicate->clause[j]; j++) new_predicate = remap_predicate_after_duplication (es->predicate,
if (!(possible_truths & es->predicate->clause[j])) possible_truths,
{ info);
new_predicate = false_predicate ();
break;
}
else
add_clause (info->conds, &new_predicate,
possible_truths & es->predicate->clause[j]);
if (false_predicate_p (&new_predicate) if (false_predicate_p (&new_predicate)
&& !false_predicate_p (es->predicate)) && !false_predicate_p (es->predicate))
{ {
...@@ -1097,22 +1161,15 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -1097,22 +1161,15 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
Also copy constantness arrays. */ Also copy constantness arrays. */
for (edge = dst->indirect_calls; edge; edge = edge->next_callee) for (edge = dst->indirect_calls; edge; edge = edge->next_callee)
{ {
struct predicate new_predicate = true_predicate (); struct predicate new_predicate;
struct inline_edge_summary *es = inline_edge_summary (edge); struct inline_edge_summary *es = inline_edge_summary (edge);
if (!edge->inline_failed) gcc_checking_assert (edge->inline_failed);
inlined_to_p = true;
if (!es->predicate) if (!es->predicate)
continue; continue;
for (j = 0; es->predicate->clause[j]; j++) new_predicate = remap_predicate_after_duplication (es->predicate,
if (!(possible_truths & es->predicate->clause[j])) possible_truths,
{ info);
new_predicate = false_predicate ();
break;
}
else
add_clause (info->conds, &new_predicate,
possible_truths & es->predicate->clause[j]);
if (false_predicate_p (&new_predicate) if (false_predicate_p (&new_predicate)
&& !false_predicate_p (es->predicate)) && !false_predicate_p (es->predicate))
{ {
...@@ -1124,28 +1181,12 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -1124,28 +1181,12 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
} }
edge_set_predicate (edge, &new_predicate); edge_set_predicate (edge, &new_predicate);
} }
if (info->loop_iterations) remap_hint_predicate_after_duplication (&info->loop_iterations,
{ possible_truths,
struct predicate new_predicate = true_predicate (); info);
remap_hint_predicate_after_duplication (&info->loop_stride,
for (j = 0; info->loop_iterations->clause[j]; j++) possible_truths,
if (!(possible_truths & info->loop_iterations->clause[j])) info);
{
new_predicate = false_predicate ();
break;
}
else
add_clause (info->conds, &new_predicate,
possible_truths & info->loop_iterations->clause[j]);
if (false_predicate_p (&new_predicate)
|| true_predicate_p (&new_predicate))
info->loop_iterations = NULL;
else
{
info->loop_iterations = (struct predicate *)pool_alloc (edge_predicate_pool);
*info->loop_iterations = new_predicate;
}
}
/* If inliner or someone after inliner will ever start producing /* If inliner or someone after inliner will ever start producing
non-trivial clones, we will get trouble with lack of information non-trivial clones, we will get trouble with lack of information
...@@ -1175,8 +1216,14 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -1175,8 +1216,14 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
if (info->loop_iterations) if (info->loop_iterations)
{ {
predicate p = *info->loop_iterations; predicate p = *info->loop_iterations;
info->loop_iterations = (struct predicate *)pool_alloc (edge_predicate_pool); info->loop_iterations = NULL;
*info->loop_iterations = p; set_hint_predicate (&info->loop_iterations, p);
}
if (info->loop_stride)
{
predicate p = *info->loop_stride;
info->loop_stride = NULL;
set_hint_predicate (&info->loop_stride, p);
} }
} }
} }
...@@ -1355,6 +1402,11 @@ dump_inline_summary (FILE * f, struct cgraph_node *node) ...@@ -1355,6 +1402,11 @@ dump_inline_summary (FILE * f, struct cgraph_node *node)
fprintf (f, " loop iterations:"); fprintf (f, " loop iterations:");
dump_predicate (f, s->conds, s->loop_iterations); dump_predicate (f, s->conds, s->loop_iterations);
} }
if (s->loop_stride)
{
fprintf (f, " loop stride:");
dump_predicate (f, s->conds, s->loop_stride);
}
fprintf (f, " calls:\n"); fprintf (f, " calls:\n");
dump_inline_edge_summary (f, 4, node, s); dump_inline_edge_summary (f, 4, node, s);
fprintf (f, "\n"); fprintf (f, "\n");
...@@ -1851,13 +1903,37 @@ will_be_nonconstant_expr_predicate (struct ipa_node_params *info, ...@@ -1851,13 +1903,37 @@ will_be_nonconstant_expr_predicate (struct ipa_node_params *info,
if (TREE_CODE (expr) == SSA_NAME) if (TREE_CODE (expr) == SSA_NAME)
return VEC_index (predicate_t, nonconstant_names, return VEC_index (predicate_t, nonconstant_names,
SSA_NAME_VERSION (expr)); SSA_NAME_VERSION (expr));
if (BINARY_CLASS_P (expr)) if (BINARY_CLASS_P (expr)
|| COMPARISON_CLASS_P (expr))
{
struct predicate p1 = will_be_nonconstant_expr_predicate
(info, summary, TREE_OPERAND (expr, 0),
nonconstant_names);
struct predicate p2;
if (true_predicate_p (&p1))
return p1;
p2 = will_be_nonconstant_expr_predicate (info, summary,
TREE_OPERAND (expr, 1),
nonconstant_names);
return or_predicates (summary->conds, &p1, &p2);
}
else if (TREE_CODE (expr) == COND_EXPR)
{ {
struct predicate p1 = will_be_nonconstant_expr_predicate (info, summary, TREE_OPERAND (expr, 0), nonconstant_names); struct predicate p1 = will_be_nonconstant_expr_predicate
(info, summary, TREE_OPERAND (expr, 0),
nonconstant_names);
struct predicate p2; struct predicate p2;
if (true_predicate_p (&p1)) if (true_predicate_p (&p1))
return p1; return p1;
p2 = will_be_nonconstant_expr_predicate (info, summary, TREE_OPERAND (expr, 0), nonconstant_names); p2 = will_be_nonconstant_expr_predicate (info, summary,
TREE_OPERAND (expr, 1),
nonconstant_names);
if (true_predicate_p (&p2))
return p2;
p1 = or_predicates (summary->conds, &p1, &p2);
p2 = will_be_nonconstant_expr_predicate (info, summary,
TREE_OPERAND (expr, 2),
nonconstant_names);
return or_predicates (summary->conds, &p1, &p2); return or_predicates (summary->conds, &p1, &p2);
} }
else else
...@@ -2390,6 +2466,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) ...@@ -2390,6 +2466,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
struct loop *loop; struct loop *loop;
loop_iterator li; loop_iterator li;
predicate loop_iterations = true_predicate (); predicate loop_iterations = true_predicate ();
predicate loop_stride = true_predicate ();
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
flow_loops_dump (dump_file, NULL, 0); flow_loops_dump (dump_file, NULL, 0);
...@@ -2398,8 +2475,9 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) ...@@ -2398,8 +2475,9 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
{ {
VEC (edge, heap) *exits; VEC (edge, heap) *exits;
edge ex; edge ex;
unsigned int j; unsigned int j, i;
struct tree_niter_desc niter_desc; struct tree_niter_desc niter_desc;
basic_block *body = get_loop_body (loop);
exits = get_loop_exit_edges (loop); exits = get_loop_exit_edges (loop);
FOR_EACH_VEC_ELT (edge, exits, j, ex) FOR_EACH_VEC_ELT (edge, exits, j, ex)
...@@ -2416,12 +2494,39 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) ...@@ -2416,12 +2494,39 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
loop_iterations = and_predicates (info->conds, &loop_iterations, &will_be_nonconstant); loop_iterations = and_predicates (info->conds, &loop_iterations, &will_be_nonconstant);
} }
VEC_free (edge, heap, exits); VEC_free (edge, heap, exits);
for (i = 0; i < loop->num_nodes; i++)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
affine_iv iv;
ssa_op_iter iter;
tree use;
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
predicate will_be_nonconstant;
if (!simple_iv (loop, loop_containing_stmt (stmt), use, &iv, true)
|| is_gimple_min_invariant (iv.step))
continue;
will_be_nonconstant
= will_be_nonconstant_expr_predicate (parms_info, info,
iv.step, nonconstant_names);
if (!true_predicate_p (&will_be_nonconstant)
&& !false_predicate_p (&will_be_nonconstant))
/* This is slightly inprecise. We may want to represent each loop with
independent predicate. */
loop_stride = and_predicates (info->conds, &loop_stride, &will_be_nonconstant);
}
}
}
free (body);
} }
if (!true_predicate_p (&loop_iterations)) set_hint_predicate (&inline_summary (node)->loop_iterations, loop_iterations);
{ set_hint_predicate (&inline_summary (node)->loop_stride, loop_stride);
inline_summary (node)->loop_iterations = (struct predicate *)pool_alloc (edge_predicate_pool);
*inline_summary (node)->loop_iterations = loop_iterations;
}
scev_finalize (); scev_finalize ();
} }
inline_summary (node)->self_time = time; inline_summary (node)->self_time = time;
...@@ -2715,6 +2820,9 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -2715,6 +2820,9 @@ estimate_node_size_and_time (struct cgraph_node *node,
if (info->loop_iterations if (info->loop_iterations
&& !evaluate_predicate (info->loop_iterations, possible_truths)) && !evaluate_predicate (info->loop_iterations, possible_truths))
hints |=INLINE_HINT_loop_iterations; hints |=INLINE_HINT_loop_iterations;
if (info->loop_stride
&& !evaluate_predicate (info->loop_stride, possible_truths))
hints |=INLINE_HINT_loop_stride;
if (time > MAX_TIME * INLINE_TIME_SCALE) if (time > MAX_TIME * INLINE_TIME_SCALE)
time = MAX_TIME * INLINE_TIME_SCALE; time = MAX_TIME * INLINE_TIME_SCALE;
...@@ -3011,6 +3119,37 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, ...@@ -3011,6 +3119,37 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
} }
} }
/* Same as remap_predicate, but set result into hint *HINT. */
static void
remap_hint_predicate (struct inline_summary *info,
struct inline_summary *callee_info,
struct predicate **hint,
VEC (int, heap) *operand_map,
VEC (int, heap) *offset_map,
clause_t possible_truths,
struct predicate *toplev_predicate)
{
predicate p;
if (!*hint)
return;
p = remap_predicate (info, callee_info,
*hint,
operand_map, offset_map,
possible_truths,
toplev_predicate);
if (!false_predicate_p (&p)
&& !true_predicate_p (&p))
{
if (!*hint)
set_hint_predicate (hint, p);
else
**hint = and_predicates (info->conds,
*hint,
&p);
}
}
/* We inlined EDGE. Update summary of the function we inlined into. */ /* We inlined EDGE. Update summary of the function we inlined into. */
...@@ -3102,28 +3241,14 @@ inline_merge_summary (struct cgraph_edge *edge) ...@@ -3102,28 +3241,14 @@ inline_merge_summary (struct cgraph_edge *edge)
} }
remap_edge_summaries (edge, edge->callee, info, callee_info, operand_map, remap_edge_summaries (edge, edge->callee, info, callee_info, operand_map,
offset_map, clause, &toplev_predicate); offset_map, clause, &toplev_predicate);
if (callee_info->loop_iterations) remap_hint_predicate (info, callee_info,
{ &callee_info->loop_iterations,
predicate p = remap_predicate (info, callee_info, operand_map, offset_map,
callee_info->loop_iterations, clause, &toplev_predicate);
operand_map, offset_map, remap_hint_predicate (info, callee_info,
clause, &callee_info->loop_stride,
&toplev_predicate); operand_map, offset_map,
if (!false_predicate_p (&p) clause, &toplev_predicate);
&& !true_predicate_p (&p))
{
if (!info->loop_iterations)
{
info->loop_iterations
= (struct predicate *)pool_alloc (edge_predicate_pool);
*info->loop_iterations = p;
}
else
*info->loop_iterations = and_predicates (info->conds,
info->loop_iterations,
&p);
}
}
inline_update_callee_summaries (edge->callee, inline_update_callee_summaries (edge->callee,
inline_edge_summary (edge)->loop_depth); inline_edge_summary (edge)->loop_depth);
...@@ -3595,11 +3720,9 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, ...@@ -3595,11 +3720,9 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
} }
p = read_predicate (&ib); p = read_predicate (&ib);
if (!true_predicate_p (&p)) set_hint_predicate (&info->loop_iterations, p);
{ p = read_predicate (&ib);
info->loop_iterations = (struct predicate *)pool_alloc (edge_predicate_pool); set_hint_predicate (&info->loop_stride, p);
*info->loop_iterations = p;
}
for (e = node->callees; e; e = e->next_callee) for (e = node->callees; e; e = e->next_callee)
read_inline_edge_summary (&ib, e); read_inline_edge_summary (&ib, e);
for (e = node->indirect_calls; e; e = e->next_callee) for (e = node->indirect_calls; e; e = e->next_callee)
...@@ -3747,6 +3870,7 @@ inline_write_summary (void) ...@@ -3747,6 +3870,7 @@ inline_write_summary (void)
write_predicate (ob, &e->predicate); write_predicate (ob, &e->predicate);
} }
write_predicate (ob, info->loop_iterations); write_predicate (ob, info->loop_iterations);
write_predicate (ob, info->loop_stride);
for (edge = node->callees; edge; edge = edge->next_callee) for (edge = node->callees; edge; edge = edge->next_callee)
write_inline_edge_summary (ob, edge); write_inline_edge_summary (ob, edge);
for (edge = node->indirect_calls; edge; edge = edge->next_callee) for (edge = node->indirect_calls; edge; edge = edge->next_callee)
......
...@@ -481,7 +481,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -481,7 +481,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
else if (DECL_DECLARED_INLINE_P (callee->symbol.decl) else if (DECL_DECLARED_INLINE_P (callee->symbol.decl)
&& growth >= MAX_INLINE_INSNS_SINGLE && growth >= MAX_INLINE_INSNS_SINGLE
&& !(hints & (INLINE_HINT_indirect_call && !(hints & (INLINE_HINT_indirect_call
| INLINE_HINT_loop_iterations))) | INLINE_HINT_loop_iterations
| INLINE_HINT_loop_stride)))
{ {
e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT; e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
want_inline = false; want_inline = false;
...@@ -533,7 +534,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -533,7 +534,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
inlining given function is very profitable. */ inlining given function is very profitable. */
else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl) else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl)
&& growth >= ((hints & (INLINE_HINT_indirect_call && growth >= ((hints & (INLINE_HINT_indirect_call
| INLINE_HINT_loop_iterations)) | INLINE_HINT_loop_iterations
| INLINE_HINT_loop_stride))
? MAX (MAX_INLINE_INSNS_AUTO, ? MAX (MAX_INLINE_INSNS_AUTO,
MAX_INLINE_INSNS_SINGLE) MAX_INLINE_INSNS_SINGLE)
: MAX_INLINE_INSNS_AUTO)) : MAX_INLINE_INSNS_AUTO))
...@@ -866,7 +868,8 @@ edge_badness (struct cgraph_edge *edge, bool dump) ...@@ -866,7 +868,8 @@ edge_badness (struct cgraph_edge *edge, bool dump)
fprintf (dump_file, "Badness overflow\n"); fprintf (dump_file, "Badness overflow\n");
} }
if (hints & (INLINE_HINT_indirect_call if (hints & (INLINE_HINT_indirect_call
| INLINE_HINT_loop_iterations)) | INLINE_HINT_loop_iterations
| INLINE_HINT_loop_stride))
badness /= 8; badness /= 8;
if (dump) if (dump)
{ {
......
...@@ -46,7 +46,8 @@ typedef struct GTY(()) condition ...@@ -46,7 +46,8 @@ typedef struct GTY(()) condition
They are represtented as bitmap of the following values. */ They are represtented as bitmap of the following values. */
enum inline_hints_vals { enum inline_hints_vals {
INLINE_HINT_indirect_call = 1, INLINE_HINT_indirect_call = 1,
INLINE_HINT_loop_iterations = 2 INLINE_HINT_loop_iterations = 2,
INLINE_HINT_loop_stride = 4
}; };
typedef int inline_hints; typedef int inline_hints;
...@@ -120,9 +121,12 @@ struct GTY(()) inline_summary ...@@ -120,9 +121,12 @@ struct GTY(()) inline_summary
conditions conds; conditions conds;
VEC(size_time_entry,gc) *entry; VEC(size_time_entry,gc) *entry;
/* Predicate on when some loop in the function sbecomes to have known /* Predicate on when some loop in the function becomes to have known
bounds. */ bounds. */
struct predicate * GTY((skip)) loop_iterations; struct predicate * GTY((skip)) loop_iterations;
/* Predicate on when some loop in the function becomes to have known
stride. */
struct predicate * GTY((skip)) loop_stride;
}; };
......
2012-09-12 Jan Hubicka <jh@suse.cz>
* gcc.dg/ipa/inlinehint-2.c: New testcase.
2012-09-12 H.J. Lu <hongjiu.lu@intel.com> 2012-09-12 H.J. Lu <hongjiu.lu@intel.com>
PR target/54445 PR target/54445
......
/* { dg-options "-O3 -c -fdump-ipa-inline-details -fno-early-inlining -fno-ipa-cp" } */
t(int s, void **p)
{
int i;
for (i;i<10000;i+=s)
p[i]=0;
}
m(void **p)
{
t (10, p);
}
/* { dg-final { scan-ipa-dump "loop_stride" "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment