diff options
author | Martin Liska <mliska@suse.cz> | 2019-07-04 17:59:19 +0200 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2019-07-04 15:59:19 +0000 |
commit | c80ab4a34c3c3761a91459755e9f632f64c99259 (patch) | |
tree | bf5aeca394c04d8447ed83b34be19552a09c2721 /gcc/tree-ssa-loop-niter.c | |
parent | ee118c14f71f43a4b82c439cd4381e034bd2786a (diff) | |
download | gcc-c80ab4a34c3c3761a91459755e9f632f64c99259.zip gcc-c80ab4a34c3c3761a91459755e9f632f64c99259.tar.gz gcc-c80ab4a34c3c3761a91459755e9f632f64c99259.tar.bz2 |
Support __builtin_expect_with_probability for analysis of # of loop iterations.
2019-07-04 Martin Liska <mliska@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.
From-SVN: r273087
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index f513859..5e75a41 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; |