[PATCH] D11196: Create a wrapper pass for BlockFrequencyInfo so that block frequency analysis can be done without requiring a pass.

Cong Hou congh at google.com
Tue Jul 14 15:45:05 PDT 2015


Thank you very much for your review! I have updated the patch
according to your comments.

Cong

On Tue, Jul 14, 2015 at 2:49 PM, Duncan P. N. Exon Smith
<dexonsmith at apple.com> wrote:
>
>> On 2015-Jul-14, at 13:47, Cong Hou <congh at google.com> wrote:
>>
>> congh created this revision.
>> congh added a reviewer: dexonsmith.
>> congh added subscribers: llvm-commits, davidxl.
>>
>> There are already several wrapper passes in LLVM such as LoopInfoWrapperPass and DominatorTreeWrapperPass. The benefit of a wrapper pass is to decouple the analysis from the function pass. This patch creates a wrapper pass for BlockFrequencyInfo. This is useful when we want to do block frequency analysis conditionally (e.g. only in PGO mode) but don't want to add one more pass dependence.
>>
>> http://reviews.llvm.org/D11196
>>
>> Files:
>>  include/llvm/Analysis/BlockFrequencyInfo.h
>>  include/llvm/InitializePasses.h
>>  lib/Analysis/Analysis.cpp
>>  lib/Analysis/BlockFrequencyInfo.cpp
>>  lib/Transforms/Vectorize/LoopVectorize.cpp
>>
>> <D11196.29708.patch>
>
>> Index: lib/Transforms/Vectorize/LoopVectorize.cpp
>> ===================================================================
>> --- lib/Transforms/Vectorize/LoopVectorize.cpp
>> +++ lib/Transforms/Vectorize/LoopVectorize.cpp
>> @@ -1454,7 +1454,7 @@
>>      LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
>>      TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
>>      DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>> -    BFI = &getAnalysis<BlockFrequencyInfo>();
>> +    BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBlockFrequencyInfo();
>
> 80-column?
>
> Looks like there's precedent for `getBFI()` (looking a few lines up, I
> see `getTTI()`).  If you rename the accessors that'll fix the whitespace
> problem here too.

Done. This is now renamed to getBFI().

>
>>      auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
>>      TLI = TLIP ? &TLIP->getTLI() : nullptr;
>>      AA = &getAnalysis<AliasAnalysis>();
>> Index: lib/Analysis/BlockFrequencyInfo.cpp
>> ===================================================================
>> --- lib/Analysis/BlockFrequencyInfo.cpp
>> +++ lib/Analysis/BlockFrequencyInfo.cpp
>> @@ -105,45 +105,15 @@
>>  } // end namespace llvm
>>  #endif
>>
>> -INITIALIZE_PASS_BEGIN(BlockFrequencyInfo, "block-freq",
>> -                      "Block Frequency Analysis", true, true)
>> -INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfo)
>> -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
>> -INITIALIZE_PASS_END(BlockFrequencyInfo, "block-freq",
>> -                    "Block Frequency Analysis", true, true)
>> -
>> -char BlockFrequencyInfo::ID = 0;
>> -
>> -
>> -BlockFrequencyInfo::BlockFrequencyInfo() : FunctionPass(ID) {
>> -  initializeBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
>> -}
>> -
>> -BlockFrequencyInfo::~BlockFrequencyInfo() {}
>> -
>> -void BlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
>> -  AU.addRequired<BranchProbabilityInfo>();
>> -  AU.addRequired<LoopInfoWrapperPass>();
>> -  AU.setPreservesAll();
>> -}
>> -
>> -bool BlockFrequencyInfo::runOnFunction(Function &F) {
>> -  BranchProbabilityInfo &BPI = getAnalysis<BranchProbabilityInfo>();
>> -  LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
>> +void BlockFrequencyInfo::recalculate(Function *F, BranchProbabilityInfo *BPI,
>> +                                     LoopInfo *LI) {
>
> Can you take these by reference?  They're not really nullable, and I
> think the references make the clear.
>
> If you can get away with it (not sure), might as well change them to
> `const` as well.  BFI shouldn't be modifying anything.

This is both done on this function and doFunction (which is now
renamed to calculate).

>
>>    if (!BFI)
>>      BFI.reset(new ImplType);
>> -  BFI->doFunction(&F, &BPI, &LI);
>> +  BFI->doFunction(F, BPI, LI);
>
> (Feel free to do the same to `doFunction()` -- change it to a reference
> -- in a separate commit if you get a chance.  Also free feel to rename
> it to something like `calculate` or whatever strikes your fancy; the
> `doFunction()` predates me and I don't think much of it.  No need for
> pre-commit review there if you decide to improve those.)

Done.

>
>>  #ifndef NDEBUG
>>    if (ViewBlockFreqPropagationDAG != GVDT_None)
>>      view();
>>  #endif
>> -  return false;
>> -}
>> -
>> -void BlockFrequencyInfo::releaseMemory() { BFI.reset(); }
>> -
>> -void BlockFrequencyInfo::print(raw_ostream &O, const Module *) const {
>> -  if (BFI) BFI->print(O);
>>  }
>>
>>  BlockFrequency BlockFrequencyInfo::getBlockFreq(const BasicBlock *BB) const {
>> @@ -180,3 +150,48 @@
>>  uint64_t BlockFrequencyInfo::getEntryFreq() const {
>>    return BFI ? BFI->getEntryFreq() : 0;
>>  }
>> +
>> +void BlockFrequencyInfo::releaseMemory() { BFI.reset(); }
>> +
>> +void BlockFrequencyInfo::print(raw_ostream &O) const {
>
> I know this is copy/paste, but I slightly prefer `OS` (and have seen
> that more often).

Done.

>
>> +  if (BFI)
>> +    BFI->print(O);
>> +}
>> +
>> +
>> +INITIALIZE_PASS_BEGIN(BlockFrequencyInfoWrapperPass, "block-freq",
>> +                      "Block Frequency Analysis", true, true)
>> +INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfo)
>> +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
>> +INITIALIZE_PASS_END(BlockFrequencyInfoWrapperPass, "block-freq",
>> +                    "Block Frequency Analysis", true, true)
>> +
>> +char BlockFrequencyInfoWrapperPass::ID = 0;
>> +
>> +
>> +BlockFrequencyInfoWrapperPass::BlockFrequencyInfoWrapperPass()
>> +    : FunctionPass(ID) {
>> +  initializeBlockFrequencyInfoWrapperPassPass(*PassRegistry::getPassRegistry());
>
> Is this duplication, "PassPass", really the way to go?
>
> Should the class just be called `BlockFrequencyInfoWrapper` so that we
> just end up with `initializeBlockFrequencyInfoWrapperPass()`?  If all
> the prior art duplicates "Pass" I guess it's okay, but it reads pretty
> badly to me.

There are already several wrapper passes named in this way:
TargetLibraryInfoWrapperPass, LoopInfoWrapperPass,
CallGraphWrapperPass, and DominatorTreeWrapperPass. I think probably
it is ok to follow this naming tradition.

>
>> +}
>> +
>> +BlockFrequencyInfoWrapperPass::~BlockFrequencyInfoWrapperPass() {}
>> +
>> +void BlockFrequencyInfoWrapperPass::print(raw_ostream &O,
>> +                                          const Module *) const {
>
> I slightly prefer `OS` here too.
>
>> +  BFI.print(O);
>> +}
>> +
>> +void BlockFrequencyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
>> +  AU.addRequired<BranchProbabilityInfo>();
>> +  AU.addRequired<LoopInfoWrapperPass>();
>> +  AU.setPreservesAll();
>> +}
>> +
>> +void BlockFrequencyInfoWrapperPass::releaseMemory() { BFI.releaseMemory(); }
>> +
>> +bool BlockFrequencyInfoWrapperPass::runOnFunction(Function &F) {
>> +  BranchProbabilityInfo &BPI = getAnalysis<BranchProbabilityInfo>();
>> +  LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
>> +  BFI.recalculate(&F, &BPI, &LI);
>> +  return false;
>> +}
>> Index: include/llvm/Analysis/BlockFrequencyInfo.h
>> ===================================================================
>> --- include/llvm/Analysis/BlockFrequencyInfo.h
>> +++ include/llvm/Analysis/BlockFrequencyInfo.h
>> @@ -21,26 +21,19 @@
>>  namespace llvm {
>>
>>  class BranchProbabilityInfo;
>> +class LoopInfo;
>>  template <class BlockT> class BlockFrequencyInfoImpl;
>>
>>  /// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to
>>  /// estimate IR basic block frequencies.
>> -class BlockFrequencyInfo : public FunctionPass {
>> +class BlockFrequencyInfo {
>>    typedef BlockFrequencyInfoImpl<BasicBlock> ImplType;
>>    std::unique_ptr<ImplType> BFI;
>>
>>  public:
>> -  static char ID;
>> -
>> -  BlockFrequencyInfo();
>> -
>> -  ~BlockFrequencyInfo() override;
>> +  BlockFrequencyInfo() = default;
>> +  ~BlockFrequencyInfo() = default;
>
> Can you just delete these?

Done.

>
>>
>> -  void getAnalysisUsage(AnalysisUsage &AU) const override;
>> -
>> -  bool runOnFunction(Function &F) override;
>> -  void releaseMemory() override;
>> -  void print(raw_ostream &O, const Module *M) const override;
>>    const Function *getFunction() const;
>>    void view() const;
>>
>> @@ -51,6 +44,9 @@
>>    /// floating points.
>>    BlockFrequency getBlockFreq(const BasicBlock *BB) const;
>>
>> +  /// recalculate - compute block frequency info for the given function.
>> +  void recalculate(Function *F, BranchProbabilityInfo *BPI, LoopInfo *LI);
>> +
>>    // Print the block frequency Freq to OS using the current functions entry
>>    // frequency to convert freq into a relative decimal form.
>>    raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const;
>> @@ -60,7 +56,28 @@
>>    raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const;
>>
>>    uint64_t getEntryFreq() const;
>> +  void releaseMemory();
>> +  void print(raw_ostream &O) const;
>> +};
>> +
>> +/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo.
>> +class BlockFrequencyInfoWrapperPass : public FunctionPass {
>> +  BlockFrequencyInfo BFI;
>>
>> +public:
>> +  static char ID;
>> +
>> +  BlockFrequencyInfoWrapperPass();
>> +  ~BlockFrequencyInfoWrapperPass() override;
>> +
>> +  BlockFrequencyInfo &getBlockFrequencyInfo() { return BFI; }
>> +  const BlockFrequencyInfo &getBlockFrequencyInfo() const { return BFI; }
>
> (These are what I think I'd rename to `getBFI()`.)

Done.

>
>> +
>> +  void getAnalysisUsage(AnalysisUsage &AU) const override;
>> +
>> +  bool runOnFunction(Function &F) override;
>> +  void releaseMemory() override;
>> +  void print(raw_ostream &O, const Module *M) const override;
>>  };
>>
>>  }
>>
>




More information about the llvm-commits mailing list