> Hi. > > The patch makes a loop upper bound estimation based on > __builtin_expect_with_probability. > > Patch can bootstrap on x86_64-linux-gnu and survives regression tests. > > The patch is pre-approved by Honza. > Thanks, > Martin > > gcc/ChangeLog: > > 2019-07-04 Martin Liska <mli...@suse.cz> > > * tree-ssa-loop-niter.c > (get_upper_bound_based_on_builtin_expr_with_prob): > New function. > (estimate_numbers_of_iterations): > Support __builtin_expect_with_probability for analysis > of # of loop iterations.
perhaps we want to also document that builtin-expect can be used this way? It owuld be also nice to have a testcase. Honza > --- > gcc/tree-ssa-loop-niter.c | 66 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 66 insertions(+) > > > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c > index f51385900ed..5e75a412d93 100644 > --- a/gcc/tree-ssa-loop-niter.c > +++ b/gcc/tree-ssa-loop-niter.c > @@ -4183,6 +4183,55 @@ maybe_lower_iteration_bound (struct loop *loop) > delete not_executed_last_iteration; > } > > +/* Get expected upper bound for number of loop iterations for > + BUILT_IN_EXPECT_WITH_PROBABILITY for a condition COND. */ > + > +static tree > +get_upper_bound_based_on_builtin_expr_with_prob (gcond *cond) > +{ > + if (cond == NULL) > + return NULL_TREE; > + > + tree lhs = gimple_cond_lhs (cond); > + if (TREE_CODE (lhs) != SSA_NAME) > + return NULL_TREE; > + > + gimple *stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (cond)); > + gcall *def = dyn_cast<gcall *> (stmt); > + if (def == NULL) > + return NULL_TREE; > + > + tree decl = gimple_call_fndecl (def); > + if (!decl > + || !fndecl_built_in_p (decl, BUILT_IN_EXPECT_WITH_PROBABILITY) > + || gimple_call_num_args (stmt) != 3) > + return NULL_TREE; > + > + tree c = gimple_call_arg (def, 1); > + tree condt = TREE_TYPE (lhs); > + tree res = fold_build2 (gimple_cond_code (cond), > + condt, c, > + gimple_cond_rhs (cond)); > + if (TREE_CODE (res) != INTEGER_CST) > + return NULL_TREE; > + > + > + tree prob = gimple_call_arg (def, 2); > + tree t = TREE_TYPE (prob); > + tree one > + = build_real_from_int_cst (t, > + integer_one_node); > + if (integer_zerop (res)) > + prob = fold_build2 (MINUS_EXPR, t, one, prob); > + tree r = fold_build2 (RDIV_EXPR, t, one, prob); > + if (TREE_CODE (r) != REAL_CST) > + return NULL_TREE; > + > + HOST_WIDE_INT probi > + = real_to_integer (TREE_REAL_CST_PTR (r)); > + return build_int_cst (condt, probi); > +} > + > /* Records estimates on numbers of iterations of LOOP. If USE_UNDEFINED_P > is true also use estimates derived from undefined behavior. */ > > @@ -4231,6 +4280,23 @@ estimate_numbers_of_iterations (struct loop *loop) > likely_exit = single_likely_exit (loop); > FOR_EACH_VEC_ELT (exits, i, ex) > { > + if (ex == likely_exit) > + { > + gimple *stmt = last_stmt (ex->src); > + if (stmt != NULL) > + { > + gcond *cond = dyn_cast<gcond *> (stmt); > + tree niter_bound > + = get_upper_bound_based_on_builtin_expr_with_prob (cond); > + if (niter_bound != NULL_TREE) > + { > + widest_int max = derive_constant_upper_bound (niter_bound); > + record_estimate (loop, niter_bound, max, cond, > + true, true, false); > + } > + } > + } > + > if (!number_of_iterations_exit (loop, ex, &niter_desc, false, false)) > continue; > >