@@ -1140,12 +1140,16 @@ void ProfileSynthesis::ComputeCyclicProbabilities(SimpleLoop* loop)
11401140 //
11411141 if (cyclicWeight > cappedLikelihood)
11421142 {
1143+ JITDUMP (" Cyclic weight " FMT_WT " > " FMT_WT " (cap) -- will reduce to cap\n " , cyclicWeight, cappedLikelihood);
11431144 capped = true ;
11441145 cyclicWeight = cappedLikelihood;
11451146 m_cappedCyclicProbabilities++;
11461147 }
11471148
1148- weight_t cyclicProbability = 1.0 / (1.0 - cyclicWeight);
1149+ // Note this value is not actually a probability; it is the expected
1150+ // iteration count of the loop.
1151+ //
1152+ weight_t const cyclicProbability = 1.0 / (1.0 - cyclicWeight);
11491153
11501154 JITDUMP (" For loop at " FMT_BB " cyclic weight is " FMT_WT " cyclic probability is " FMT_WT " %s\n " ,
11511155 loop->m_head ->bbNum , cyclicWeight, cyclicProbability, capped ? " [capped]" : " " );
@@ -1154,50 +1158,102 @@ void ProfileSynthesis::ComputeCyclicProbabilities(SimpleLoop* loop)
11541158
11551159 // Try and adjust loop exit likelihood to reflect capping.
11561160 // If there are multiple exits we just adjust the first one we can. This is somewhat arbitrary.
1161+ // If there are no exits, there's nothing we can do.
11571162 //
1158- if (capped)
1163+ if (capped && (loop-> m_exitEdges . size () > 0 ) )
11591164 {
1160- bool adjustedExit = false ;
1165+ // Figure out how much flow exits the loop with the capped probablility
1166+ // and current block frequencies and exit likelihoods.
1167+ //
1168+ weight_t cappedExitWeight = 0.0 ;
11611169
11621170 for (FlowEdge* const exitEdge : loop->m_exitEdges )
11631171 {
1164- BasicBlock* const exitBlock = exitEdge->getSourceBlock ();
1172+ BasicBlock* const exitBlock = exitEdge->getSourceBlock ();
1173+ weight_t const exitBlockFrequency = exitBlock->bbWeight ;
1174+ weight_t const exitBlockWeight = exitBlockFrequency * cyclicProbability;
1175+ weight_t const exitWeight = exitEdge->getLikelihood () * exitBlockWeight;
1176+ cappedExitWeight += exitWeight;
1177+ JITDUMP (" Exit from " FMT_BB " has weight " FMT_WT " \n " , exitBlock->bbNum , exitWeight);
1178+ }
1179+
1180+ JITDUMP (" Total exit weight " FMT_WT " \n " , cappedExitWeight);
1181+
1182+ // We should end up with a value less than one since we input one unit of flow into the
1183+ // loop and are artificially capping the iteration count of the loop, so less weight is
1184+ // now flowing out than in. However because of rounding we might end up near or a bit over 1.0.
1185+ //
1186+ if ((cappedExitWeight + epsilon) < 1.0 )
1187+ {
1188+ // We want to increase the exit likelihood of one exit block to create
1189+ // additional flow out of the loop. Figure out how much we need.
1190+ //
1191+ weight_t const missingExitWeight = 1.0 - cappedExitWeight;
1192+ JITDUMP (" Loop exit flow deficit from capping is " FMT_WT " \n " , missingExitWeight);
11651193
1166- if ((exitBlock->bbJumpKind == BBJ_COND) &&
1167- !Compiler::fgProfileWeightsEqual (exitBlock->bbWeight , 0.0 , epsilon))
1194+ bool adjustedExit = false ;
1195+
1196+ for (FlowEdge* const exitEdge : loop->m_exitEdges )
11681197 {
1169- JITDUMP (" Will adjust likelihood of the exit edge from loop exit block " FMT_BB
1170- " to reflect capping; current likelihood is " FMT_WT " \n " ,
1171- exitBlock->bbNum , exitEdge->getLikelihood ());
1172-
1173- BasicBlock* const jump = exitBlock->bbJumpDest ;
1174- BasicBlock* const next = exitBlock->bbNext ;
1175- FlowEdge* const jumpEdge = m_comp->fgGetPredForBlock (jump, exitBlock);
1176- FlowEdge* const nextEdge = m_comp->fgGetPredForBlock (next, exitBlock);
1177- weight_t const continueLikelihood = cappedLikelihood / exitBlock->bbWeight ;
1178- weight_t const breakLikelihood = 1 - continueLikelihood;
1179-
1180- if (jumpEdge == exitEdge)
1181- {
1182- jumpEdge->setLikelihood (breakLikelihood);
1183- nextEdge->setLikelihood (continueLikelihood);
1184- }
1185- else
1198+ // Does this block have enough weight that it can supply all the missing weight?
1199+ //
1200+ BasicBlock* const exitBlock = exitEdge->getSourceBlock ();
1201+ weight_t const exitBlockFrequency = exitBlock->bbWeight ;
1202+ weight_t const exitBlockWeight = exitBlockFrequency * cyclicProbability;
1203+ weight_t const currentExitWeight = exitEdge->getLikelihood () * exitBlockWeight;
1204+
1205+ // TODO: we might also want to exclude edges that are exiting from child loops here,
1206+ // or think harder about what might be appropriate in those cases. Seems like we ought
1207+ // to adjust an edge's likelihoods at most once.
1208+ //
1209+ // Currently we don't know which edges do this.
1210+ //
1211+ if ((exitBlock->bbJumpKind == BBJ_COND) && (exitBlockWeight > (missingExitWeight + currentExitWeight)))
11861212 {
1187- assert (nextEdge == exitEdge);
1188- jumpEdge->setLikelihood (continueLikelihood);
1189- nextEdge->setLikelihood (breakLikelihood);
1213+ JITDUMP (" Will adjust likelihood of the exit edge from loop exit block " FMT_BB
1214+ " to reflect capping; current likelihood is " FMT_WT " \n " ,
1215+ exitBlock->bbNum , exitEdge->getLikelihood ());
1216+
1217+ BasicBlock* const jump = exitBlock->bbJumpDest ;
1218+ BasicBlock* const next = exitBlock->bbNext ;
1219+ FlowEdge* const jumpEdge = m_comp->fgGetPredForBlock (jump, exitBlock);
1220+ FlowEdge* const nextEdge = m_comp->fgGetPredForBlock (next, exitBlock);
1221+ weight_t const exitLikelihood = (missingExitWeight + currentExitWeight) / exitBlockWeight;
1222+ weight_t const continueLikelihood = 1.0 - exitLikelihood;
1223+
1224+ // We are making it more likely that the loop exits, so the new exit likelihood
1225+ // should be greater than the old.
1226+ //
1227+ assert (exitLikelihood > exitEdge->getLikelihood ());
1228+
1229+ if (jumpEdge == exitEdge)
1230+ {
1231+ jumpEdge->setLikelihood (exitLikelihood);
1232+ nextEdge->setLikelihood (continueLikelihood);
1233+ }
1234+ else
1235+ {
1236+ assert (nextEdge == exitEdge);
1237+ jumpEdge->setLikelihood (continueLikelihood);
1238+ nextEdge->setLikelihood (exitLikelihood);
1239+ }
1240+ adjustedExit = true ;
1241+
1242+ JITDUMP (" New likelihood is " FMT_WT " \n " , exitEdge->getLikelihood ());
1243+ break ;
11901244 }
1191- adjustedExit = true ;
1245+ }
11921246
1193- JITDUMP (" New likelihood is " FMT_WT " \n " , exitEdge->getLikelihood ());
1194- break ;
1247+ if (!adjustedExit)
1248+ {
1249+ // Possibly we could have fixed things up by adjusting more than one exit?
1250+ //
1251+ JITDUMP (" Unable to find suitable exit to carry off capped flow\n " );
11951252 }
11961253 }
1197-
1198- if (!adjustedExit)
1254+ else
11991255 {
1200- JITDUMP (" Unable to find suitable exit to carry off capped flow \n " );
1256+ JITDUMP (" Exit weight comparable or above 1.0, leaving as is \n " );
12011257 }
12021258 }
12031259}
0 commit comments