Hi, this is a new version of the patch which makes ipa analysis produce predicates for PHI node results, at least at the bottom of the simplest diamond and semi-diamond CFG subgraphs. This time I also analyze the conditions again rather than extracting information from CFG edges, which means I can reason about substantially more PHI nodes.
This patch makes us produce loop bounds hint for the pr48636.f90 testcase. Bootstrapped and tested on x86_64-linux. OK for trunk? Thanks, Martin 2012-08-29 Martin Jambor <mjam...@suse.cz> * ipa-inline-analysis.c (phi_result_unknown_predicate): New function. (predicate_for_phi_result): Likewise. (estimate_function_body_sizes): Use the above two functions. Index: src/gcc/ipa-inline-analysis.c =================================================================== --- src.orig/gcc/ipa-inline-analysis.c +++ src/gcc/ipa-inline-analysis.c @@ -2070,6 +2070,99 @@ param_change_prob (gimple stmt, int i) return REG_BR_PROB_BASE; } +/* Find whether a basic block BB is the final block of a (half) diamond CFG + sub-graph and if the predicate the condition depends on is known. If so, + return true and store the pointer the predicate in *P. */ + +static bool +phi_result_unknown_predicate (struct ipa_node_params *info, + struct inline_summary *summary, basic_block bb, + struct predicate *p, + VEC (predicate_t, heap) *nonconstant_names) +{ + edge e; + edge_iterator ei; + basic_block first_bb = NULL; + gimple stmt; + + if (single_pred_p (bb)) + { + *p = false_predicate (); + return true; + } + + FOR_EACH_EDGE (e, ei, bb->preds) + { + if (single_succ_p (e->src)) + { + if (!single_pred_p (e->src)) + return false; + if (!first_bb) + first_bb = single_pred (e->src); + else if (single_pred (e->src) != first_bb) + return false; + } + else + { + if (!first_bb) + first_bb = e->src; + else if (e->src != first_bb) + return false; + } + } + + if (!first_bb) + return false; + + stmt = last_stmt (first_bb); + if (!stmt + || gimple_code (stmt) != GIMPLE_COND + || !is_gimple_ip_invariant (gimple_cond_rhs (stmt))) + return false; + + *p = will_be_nonconstant_expr_predicate (info, summary, + gimple_cond_lhs (stmt), + nonconstant_names); + if (true_predicate_p (p)) + return false; + else + return true; +} + +/* Given a PHI statement in a function described by inline properties SUMMARY + and *P being the predicate describing whether the selected PHI argument is + known, store a predicate for the result of the PHI statement into + NONCONSTANT_NAMES, if possible. */ + +static void +predicate_for_phi_result (struct inline_summary *summary, gimple phi, + struct predicate *p, + VEC (predicate_t, heap) *nonconstant_names) +{ + unsigned i; + + for (i = 0; i < gimple_phi_num_args (phi); i++) + { + tree arg = gimple_phi_arg (phi, i)->def; + if (!is_gimple_min_invariant (arg)) + { + gcc_assert (TREE_CODE (arg) == SSA_NAME); + *p = or_predicates (summary->conds, p, + &VEC_index (predicate_t, nonconstant_names, + SSA_NAME_VERSION (arg))); + if (true_predicate_p (p)) + return; + } + } + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "\t\tphi predicate: "); + dump_predicate (dump_file, summary->conds, p); + } + VEC_replace (predicate_t, nonconstant_names, + SSA_NAME_VERSION (gimple_phi_result (phi)), *p); +} /* Compute function body size parameters for NODE. When EARLY is true, we compute only simple summaries without @@ -2143,7 +2236,30 @@ estimate_function_body_sizes (struct cgr fprintf (dump_file, "\n BB %i predicate:", bb->index); dump_predicate (dump_file, info->conds, &bb_predicate); } - + + if (parms_info && nonconstant_names) + { + struct predicate phi_predicate; + bool first_phi = true; + + for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi)) + { + if (first_phi + && !phi_result_unknown_predicate (parms_info, info, bb, + &phi_predicate, + nonconstant_names)) + break; + first_phi = false; + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, " "); + print_gimple_stmt (dump_file, gsi_stmt (bsi), 0, 0); + } + predicate_for_phi_result (info, gsi_stmt (bsi), &phi_predicate, + nonconstant_names); + } + } + for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple stmt = gsi_stmt (bsi);