aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/gcc/predict.c b/gcc/predict.c
index d9c7249..68b1113 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -4481,6 +4481,43 @@ force_edge_cold (edge e, bool impossible)
}
}
+/* Change E's probability to NEW_E_PROB, redistributing the probabilities
+ of other outgoing edges proportionally.
+
+ Note that this function does not change the profile counts of any
+ basic blocks. The caller must do that instead, using whatever
+ information it has about the region that needs updating. */
+
+void
+change_edge_frequency (edge e, profile_probability new_e_prob)
+{
+ profile_probability old_e_prob = e->probability;
+ profile_probability old_other_prob = old_e_prob.invert ();
+ profile_probability new_other_prob = new_e_prob.invert ();
+
+ e->probability = new_e_prob;
+ profile_probability cumulative_prob = new_e_prob;
+
+ unsigned int num_other = EDGE_COUNT (e->src->succs) - 1;
+ edge other_e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (other_e, ei, e->src->succs)
+ if (other_e != e)
+ {
+ num_other -= 1;
+ if (num_other == 0)
+ /* Ensure that the probabilities add up to 1 without
+ rounding error. */
+ other_e->probability = cumulative_prob.invert ();
+ else
+ {
+ other_e->probability /= old_other_prob;
+ other_e->probability *= new_other_prob;
+ cumulative_prob += other_e->probability;
+ }
+ }
+}
+
#if CHECKING_P
namespace selftest {