From c80ab4a34c3c3761a91459755e9f632f64c99259 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 4 Jul 2019 17:59:19 +0200 Subject: [PATCH] Support __builtin_expect_with_probability for analysis of # of loop iterations. 2019-07-04 Martin Liska * 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. From-SVN: r273087 --- gcc/ChangeLog | 8 +++++ gcc/tree-ssa-loop-niter.c | 66 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41b8b14400a..d4e999194f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-04 Martin Liska + + * 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. + 2019-07-04 Alexandre Oliva * doc/generic.texi (Cleanups): Document EH_ELSE_EXPR. 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 (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 (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; -- 2.30.2