[LazyMachineBFI] Reimplement with getAnalysisIfAvailable

Since LoopInfo is not available in machine passes as universally as in IR
passes, using the same approach for OptimizationRemarkEmitter as we did for IR
will run LoopInfo and DominatorTree unnecessarily.  (LoopInfo is not used
lazily by ORE.)

To fix this, I am modifying the approach I took in D29836.  LazyMachineBFI now
uses its client passes including MachineBFI itself that are available or
otherwise compute them on the fly.

So for example GreedyRegAlloc, since it's already using MBFI, will reuse that
instance.  On the other hand, AsmPrinter in Justin's patch will generate DT,
LI and finally BFI on the fly.

(I am of course wondering now if the simplicity of this approach is even
preferable in IR.  I will do some experiments.)

Testing is provided by an updated version of D29837 which requires Justin's
patch to bring ORE to the AsmPrinter.

Differential Revision: https://reviews.llvm.org/D30128

llvm-svn: 295996
This commit is contained in:
Adam Nemet 2017-02-23 17:30:01 +00:00
parent 3f4181db66
commit b516cf3f3f
3 changed files with 66 additions and 50 deletions

View File

@ -17,9 +17,9 @@
#ifndef LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H
#define LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H
#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
namespace llvm {
@ -28,30 +28,30 @@ namespace llvm {
/// computed when the analysis pass is executed but rather when the BFI result
/// is explicitly requested by the analysis client.
///
/// There are some additional requirements for any client pass that wants to use
/// the analysis:
///
/// 1. The pass needs to initialize dependent passes with:
///
/// INITIALIZE_PASS_DEPENDENCY(LazyMachineBFIPass)
///
/// 2. Similarly, getAnalysisUsage should call:
///
/// LazyMachineBlockFrequencyInfoPass::getLazyMachineBFIAnalysisUsage(AU)
///
/// 3. The computed MachineBFI should be requested with
/// getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI() before
/// MachineLoopInfo could be invalidated for example by changing the CFG.
/// This works by checking querying if MBFI is available and otherwise
/// generating MBFI on the fly. In this case the passes required for (LI, DT)
/// are also queried before being computed on the fly.
///
/// Note that it is expected that we wouldn't need this functionality for the
/// new PM since with the new PM, analyses are executed on demand.
class LazyMachineBlockFrequencyInfoPass : public MachineFunctionPass {
private:
/// \brief Machine BPI is an immutable pass, no need to use it lazily.
LazyBlockFrequencyInfo<MachineFunction, MachineBranchProbabilityInfo,
MachineLoopInfo, MachineBlockFrequencyInfo>
LMBFI;
/// If generated on the fly this own the instance.
mutable std::unique_ptr<MachineBlockFrequencyInfo> OwnedMBFI;
/// If generated on the fly this own the instance.
mutable std::unique_ptr<MachineLoopInfo> OwnedMLI;
/// If generated on the fly this own the instance.
mutable std::unique_ptr<MachineDominatorTree> OwnedMDT;
/// The function.
MachineFunction *MF = nullptr;
/// \brief Calculate MBFI and all other analyses that's not available and
/// required by BFI.
MachineBlockFrequencyInfo &calculateIfNotAvailable() const;
public:
static char ID;
@ -59,25 +59,18 @@ public:
LazyMachineBlockFrequencyInfoPass();
/// \brief Compute and return the block frequencies.
MachineBlockFrequencyInfo &getBFI() { return LMBFI.getCalculated(); }
MachineBlockFrequencyInfo &getBFI() { return calculateIfNotAvailable(); }
/// \brief Compute and return the block frequencies.
const MachineBlockFrequencyInfo &getBFI() const {
return LMBFI.getCalculated();
return calculateIfNotAvailable();
}
void getAnalysisUsage(AnalysisUsage &AU) const override;
/// Helper for client passes to set up the analysis usage on behalf of this
/// pass.
static void getLazyMachineBFIAnalysisUsage(AnalysisUsage &AU);
bool runOnMachineFunction(MachineFunction &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M) const override;
};
/// \brief Helper for client passes to initialize dependent passes for LMBFI.
void initializeLazyMachineBFIPassPass(PassRegistry &Registry);
}
#endif

View File

@ -37,38 +37,61 @@ LazyMachineBlockFrequencyInfoPass::LazyMachineBlockFrequencyInfoPass()
void LazyMachineBlockFrequencyInfoPass::print(raw_ostream &OS,
const Module *M) const {
LMBFI.getCalculated().print(OS, M);
getBFI().print(OS, M);
}
void LazyMachineBlockFrequencyInfoPass::getAnalysisUsage(
AnalysisUsage &AU) const {
AU.addRequired<MachineBranchProbabilityInfo>();
AU.addRequired<MachineLoopInfo>();
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
void LazyMachineBlockFrequencyInfoPass::releaseMemory() {
LMBFI.releaseMemory();
OwnedMBFI.reset();
OwnedMLI.reset();
OwnedMDT.reset();
}
MachineBlockFrequencyInfo &
LazyMachineBlockFrequencyInfoPass::calculateIfNotAvailable() const {
auto *MBFI = getAnalysisIfAvailable<MachineBlockFrequencyInfo>();
if (MBFI) {
DEBUG(dbgs() << "MachineBlockFrequencyInfo is available\n");
return *MBFI;
}
auto &MBPI = getAnalysis<MachineBranchProbabilityInfo>();
auto *MLI = getAnalysisIfAvailable<MachineLoopInfo>();
auto *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
DEBUG(dbgs() << "Building MachineBlockFrequencyInfo on the fly\n");
DEBUG(if (MLI) dbgs() << "LoopInfo is available\n");
if (!MLI) {
DEBUG(dbgs() << "Building LoopInfo on the fly\n");
// First create a dominator tree.
DEBUG(if (MDT) dbgs() << "DominatorTree is available\n");
if (!MDT) {
DEBUG(dbgs() << "Building DominatorTree on the fly\n");
OwnedMDT = make_unique<MachineDominatorTree>();
OwnedMDT->getBase().recalculate(*MF);
MDT = OwnedMDT.get();
}
// Generate LoopInfo from it.
OwnedMLI = make_unique<MachineLoopInfo>();
OwnedMLI->getBase().analyze(MDT->getBase());
MLI = OwnedMLI.get();
}
OwnedMBFI = make_unique<MachineBlockFrequencyInfo>();
OwnedMBFI->calculate(*MF, MBPI, *MLI);
return *OwnedMBFI.get();
}
bool LazyMachineBlockFrequencyInfoPass::runOnMachineFunction(
MachineFunction &MF) {
auto &BPIPass = getAnalysis<MachineBranchProbabilityInfo>();
auto &LI = getAnalysis<MachineLoopInfo>();
LMBFI.setAnalysis(&MF, &BPIPass, &LI);
MachineFunction &F) {
MF = &F;
return false;
}
void LazyMachineBlockFrequencyInfoPass::getLazyMachineBFIAnalysisUsage(
AnalysisUsage &AU) {
AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
AU.addRequired<MachineBranchProbabilityInfo>();
AU.addRequired<MachineLoopInfo>();
}
void llvm::initializeLazyMachineBFIPassPass(PassRegistry &Registry) {
INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass);
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo);
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo);
}

View File

@ -74,7 +74,7 @@ bool MachineOptimizationRemarkEmitterPass::runOnMachineFunction(
void MachineOptimizationRemarkEmitterPass::getAnalysisUsage(
AnalysisUsage &AU) const {
LazyMachineBlockFrequencyInfoPass::getLazyMachineBFIAnalysisUsage(AU);
AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
@ -85,6 +85,6 @@ static const char ore_name[] = "Machine Optimization Remark Emitter";
INITIALIZE_PASS_BEGIN(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
false, true)
INITIALIZE_PASS_DEPENDENCY(LazyMachineBFIPass)
INITIALIZE_PASS_DEPENDENCY(LazyMachineBlockFrequencyInfoPass)
INITIALIZE_PASS_END(MachineOptimizationRemarkEmitterPass, ORE_NAME, ore_name,
false, true)