diff options
Diffstat (limited to 'gcc/cfg.c')
-rw-r--r-- | gcc/cfg.c | 43 |
1 files changed, 41 insertions, 2 deletions
@@ -96,6 +96,8 @@ static void free_edge (edge); /* Indicate the presence of the profile. */ enum profile_status profile_status; +#define RDIV(X,Y) (((X) + (Y) / 2) / (Y)) + /* Called once at initialization time. */ void @@ -933,10 +935,10 @@ update_bb_profile_for_threading (basic_block bb, int edge_frequency, } else if (prob != REG_BR_PROB_BASE) { - int scale = REG_BR_PROB_BASE / prob; + int scale = 65536 * REG_BR_PROB_BASE / prob; FOR_EACH_EDGE (c, ei, bb->succs) - c->probability *= scale; + c->probability *= scale / 65536; } if (bb != taken_edge->src) @@ -945,3 +947,40 @@ update_bb_profile_for_threading (basic_block bb, int edge_frequency, if (taken_edge->count < 0) taken_edge->count = 0; } + +/* Multiply all frequencies of basic blocks in array BBS of length NBBS + by NUM/DEN, in int arithmetic. May lose some accuracy. */ +void +scale_bbs_frequencies_int (basic_block *bbs, int nbbs, int num, int den) +{ + int i; + edge e; + for (i = 0; i < nbbs; i++) + { + edge_iterator ei; + bbs[i]->frequency = (bbs[i]->frequency * num) / den; + bbs[i]->count = RDIV (bbs[i]->count * num, den); + FOR_EACH_EDGE (e, ei, bbs[i]->succs) + e->count = (e->count * num) /den; + } +} + +/* Multiply all frequencies of basic blocks in array BBS of length NBBS + by NUM/DEN, in gcov_type arithmetic. More accurate than previous + function but considerably slower. */ +void +scale_bbs_frequencies_gcov_type (basic_block *bbs, int nbbs, gcov_type num, + gcov_type den) +{ + int i; + edge e; + + for (i = 0; i < nbbs; i++) + { + edge_iterator ei; + bbs[i]->frequency = (bbs[i]->frequency * num) / den; + bbs[i]->count = RDIV (bbs[i]->count * num, den); + FOR_EACH_EDGE (e, ei, bbs[i]->succs) + e->count = (e->count * num) /den; + } +} |