The following avoids quadraticness in the loop depth by only considering
loop header defs as IVs for the analysis of the loop_stride predicate.
This will miss cases like
foo (int inv)
{
for (i = inv; i < n; ++i)
{
int derived_iv = i + i * inv;
...
}
}
but I doubt that's important in practice. Another way would be to
just consider the containing loop when analyzing the IV, thus iterate
over outermost loop bodies only, replacing the
simple_iv (loop, loop_containing_stmt (stmt), use, &iv, true)
check with
simple_iv (loop_containing_stmt (stmt), loop_containing_stmt (stmt),
use, &iv, true);
but doing all this analysis for each stmt is already quite expensive,
esp. as we are doing it for all uses instead of all defs ...
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
Honza, is this ok or did you do the current way on purpose (rather
than for completeness as it was easy to do?)
Thanks,
Richard.
2015-10-01 Richard Biener <[email protected]>
PR ipa/67783
* ipa-inline-analysis.c (estimate_function_body_sizes): Only
consider loop header PHI defs as IVs.
Index: gcc/ipa-inline-analysis.c
===================================================================
*** gcc/ipa-inline-analysis.c (revision 228319)
--- gcc/ipa-inline-analysis.c (working copy)
*************** estimate_function_body_sizes (struct cgr
*** 2760,2768 ****
{
vec<edge> exits;
edge ex;
! unsigned int j, i;
struct tree_niter_desc niter_desc;
- basic_block *body = get_loop_body (loop);
bb_predicate = *(struct predicate *) loop->header->aux;
exits = get_loop_exit_edges (loop);
--- 2760,2767 ----
{
vec<edge> exits;
edge ex;
! unsigned int j;
struct tree_niter_desc niter_desc;
bb_predicate = *(struct predicate *) loop->header->aux;
exits = get_loop_exit_edges (loop);
*************** estimate_function_body_sizes (struct cgr
*** 2788,2833 ****
}
exits.release ();
! for (i = 0; i < loop->num_nodes; i++)
{
! gimple_stmt_iterator gsi;
! bb_predicate = *(struct predicate *) body[i]->aux;
! 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 (fbi.info, info,
! iv.step,
! nonconstant_names);
! if (!true_predicate_p (&will_be_nonconstant))
! will_be_nonconstant
! = and_predicates (info->conds,
! &bb_predicate,
! &will_be_nonconstant);
! 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);
}
set_hint_predicate (&inline_summaries->get (node)->loop_iterations,
loop_iterations);
--- 2787,2818 ----
}
exits.release ();
! for (gphi_iterator gsi = gsi_start_phis (loop->header);
! !gsi_end_p (gsi); gsi_next (&gsi))
{
! gphi *phi = gsi.phi ();
! tree use = gimple_phi_result (phi);
! affine_iv iv;
! predicate will_be_nonconstant;
! if (!virtual_operand_p (use)
! || !simple_iv (loop, loop, use, &iv, true)
! || is_gimple_min_invariant (iv.step))
! continue;
! will_be_nonconstant
! = will_be_nonconstant_expr_predicate (fbi.info, info,
! iv.step,
! nonconstant_names);
! if (!true_predicate_p (&will_be_nonconstant))
! will_be_nonconstant = and_predicates (info->conds,
! &bb_predicate,
! &will_be_nonconstant);
! 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);
}
}
set_hint_predicate (&inline_summaries->get (node)->loop_iterations,
loop_iterations);