aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/profile-count.cc57
-rw-r--r--gcc/profile-count.h6
-rw-r--r--gcc/tree-vect-loop-manip.cc15
3 files changed, 75 insertions, 3 deletions
diff --git a/gcc/profile-count.cc b/gcc/profile-count.cc
index eaf0f0d..e63c943 100644
--- a/gcc/profile-count.cc
+++ b/gcc/profile-count.cc
@@ -471,3 +471,60 @@ profile_probability::to_sreal () const
gcc_checking_assert (initialized_p ());
return ((sreal)m_val) >> (n_bits - 2);
}
+
+/* Compute square root. */
+
+profile_probability
+profile_probability::sqrt () const
+{
+ if (!initialized_p () || *this == never () || *this == always ())
+ return *this;
+ profile_probability ret = *this;
+ ret.m_quality = MIN (ret.m_quality, ADJUSTED);
+ uint32_t min_range = m_val;
+ uint32_t max_range = max_probability;
+ if (!m_val)
+ max_range = 0;
+ if (m_val == max_probability)
+ min_range = max_probability;
+ while (min_range != max_range)
+ {
+ uint32_t val = (min_range + max_range) / 2;
+ uint32_t val2 = RDIV ((uint64_t)val * val, max_probability);
+ if (val2 == m_val)
+ min_range = max_range = m_val;
+ else if (val2 > m_val)
+ max_range = val - 1;
+ else if (val2 < m_val)
+ min_range = val + 1;
+ }
+ ret.m_val = min_range;
+ return ret;
+}
+
+/* Compute n-th power of THIS. */
+
+profile_probability
+profile_probability::pow (int n) const
+{
+ if (n == 1 || !initialized_p ())
+ return *this;
+ if (!n)
+ return profile_probability::always ();
+ if (!nonzero_p ()
+ || !(profile_probability::always () - *this).nonzero_p ())
+ return *this;
+ profile_probability ret = profile_probability::always ();
+ profile_probability v = *this;
+ int p = 1;
+ while (true)
+ {
+ if (n & p)
+ ret = ret * v;
+ p <<= 1;
+ if (p > n)
+ break;
+ v = v * v;
+ }
+ return ret;
+}
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 88a6431..002bcb8 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -650,6 +650,12 @@ public:
return *this;
}
+ /* Compute n-th power. */
+ profile_probability pow (int) const;
+
+ /* Compute sware root. */
+ profile_probability sqrt () const;
+
/* Get the value of the count. */
uint32_t value () const { return m_val; }
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 30baac6..e53a99e 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -3784,7 +3784,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
}
tree cost_name = NULL_TREE;
- profile_probability prob2 = profile_probability::uninitialized ();
+ profile_probability prob2 = profile_probability::always ();
if (cond_expr
&& EXPR_P (cond_expr)
&& (version_niter
@@ -3797,7 +3797,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
is_gimple_val, NULL_TREE);
/* Split prob () into two so that the overall probability of passing
both the cost-model and versioning checks is the orig prob. */
- prob2 = prob.split (prob);
+ prob2 = prob = prob.sqrt ();
}
if (version_niter)
@@ -3941,7 +3941,15 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
initialize_original_copy_tables ();
nloop = loop_version (loop_to_version, cond_expr, &condition_bb,
- prob, prob.invert (), prob, prob.invert (), true);
+ prob * prob2, (prob * prob2).invert (),
+ prob * prob2, (prob * prob2).invert (),
+ true);
+ /* We will later insert second conditional so overall outcome of
+ both is prob * prob2. */
+ edge true_e, false_e;
+ extract_true_false_edges_from_block (condition_bb, &true_e, &false_e);
+ true_e->probability = prob;
+ false_e->probability = prob.invert ();
gcc_assert (nloop);
nloop = get_loop_copy (loop);
@@ -4037,6 +4045,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
edge e2 = make_edge (e->src, false_e->dest, EDGE_FALSE_VALUE);
e->probability = prob2;
e2->probability = prob2.invert ();
+ e->dest->count = e->count ();
set_immediate_dominator (CDI_DOMINATORS, false_e->dest, e->src);
auto_vec<basic_block, 3> adj;
for (basic_block son = first_dom_son (CDI_DOMINATORS, e->dest);