Index: llvm/trunk/include/llvm/Analysis/BlockFrequencyInfo.h =================================================================== --- llvm/trunk/include/llvm/Analysis/BlockFrequencyInfo.h +++ llvm/trunk/include/llvm/Analysis/BlockFrequencyInfo.h @@ -73,6 +73,12 @@ // Set the frequency of the given basic block. void setBlockFreq(const BasicBlock *BB, uint64_t Freq); + /// Set the frequency of \p ReferenceBB to \p Freq and scale the frequencies + /// of the blocks in \p BlocksToScale such that their frequencies relative + /// to \p ReferenceBB remain unchanged. + void setBlockFreqAndScale(const BasicBlock *ReferenceBB, uint64_t Freq, + SmallPtrSetImpl &BlocksToScale); + /// calculate - compute block frequency info for the given function. void calculate(const Function &F, const BranchProbabilityInfo &BPI, const LoopInfo &LI); Index: llvm/trunk/lib/Analysis/BlockFrequencyInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/BlockFrequencyInfo.cpp +++ llvm/trunk/lib/Analysis/BlockFrequencyInfo.cpp @@ -180,6 +180,28 @@ BFI->setBlockFreq(BB, Freq); } +void BlockFrequencyInfo::setBlockFreqAndScale( + const BasicBlock *ReferenceBB, uint64_t Freq, + SmallPtrSetImpl &BlocksToScale) { + assert(BFI && "Expected analysis to be available"); + // Use 128 bits APInt to avoid overflow. + APInt NewFreq(128, Freq); + APInt OldFreq(128, BFI->getBlockFreq(ReferenceBB).getFrequency()); + APInt BBFreq(128, 0); + for (auto *BB : BlocksToScale) { + BBFreq = BFI->getBlockFreq(BB).getFrequency(); + // Multiply first by NewFreq and then divide by OldFreq + // to minimize loss of precision. + BBFreq *= NewFreq; + // udiv is an expensive operation in the general case. If this ends up being + // a hot spot, one of the options proposed in + // https://reviews.llvm.org/D28535#650071 could be used to avoid this. + BBFreq = BBFreq.udiv(OldFreq); + BFI->setBlockFreq(BB, BBFreq.getLimitedValue()); + } + BFI->setBlockFreq(ReferenceBB, Freq); +} + /// Pop up a ghostview window with the current block frequency propagation /// rendered using dot. void BlockFrequencyInfo::view() const { Index: llvm/trunk/unittests/Analysis/BlockFrequencyInfoTest.cpp =================================================================== --- llvm/trunk/unittests/Analysis/BlockFrequencyInfoTest.cpp +++ llvm/trunk/unittests/Analysis/BlockFrequencyInfoTest.cpp @@ -80,6 +80,14 @@ EXPECT_EQ(BFI.getBlockProfileCount(BB3).getValue(), UINT64_C(100)); EXPECT_EQ(BFI.getBlockProfileCount(BB1).getValue(), 100 * BB1Freq / BB0Freq); EXPECT_EQ(BFI.getBlockProfileCount(BB2).getValue(), 100 * BB2Freq / BB0Freq); + + // Scale the frequencies of BB0, BB1 and BB2 by a factor of two. + SmallPtrSet BlocksToScale({BB1, BB2}); + BFI.setBlockFreqAndScale(&BB0, BB0Freq * 2, BlocksToScale); + EXPECT_EQ(BFI.getBlockFreq(&BB0).getFrequency(), 2 * BB0Freq); + EXPECT_EQ(BFI.getBlockFreq(BB1).getFrequency(), 2 * BB1Freq); + EXPECT_EQ(BFI.getBlockFreq(BB2).getFrequency(), 2 * BB2Freq); + EXPECT_EQ(BFI.getBlockFreq(BB3).getFrequency(), BB3Freq); } } // end anonymous namespace