[Polly][ScopInfo] Lazy Scop instantiation (#179535)
The old NPM was using ScopInfo pass introduced in https://reviews.llvm.org/D20962, which in contrast to the LPM was using ScopInfoRegionPass. ScopInfo was instantiating all Scop objects immediately. After codegenning, all Scop objects need to be recomputed anyway, making this approach wastful. The PhaseManager inherited this behaviour from the NPM, leading to some concerns. Replace the instantiate-all behavior of ScopInfo with an on-demand instantiation. SCoPs now must be iterated using ScopDetection instead using ScopInfo, but only some unsed legacy NPM passes (now removed) were doing that anyway.
This commit is contained in:
parent
6d91695530
commit
d5607ad55c
@ -2670,17 +2670,10 @@ public:
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Scop &scop);
|
||||
|
||||
class ScopInfo {
|
||||
public:
|
||||
using RegionToScopMapTy = MapVector<Region *, std::unique_ptr<Scop>>;
|
||||
using reverse_iterator = RegionToScopMapTy::reverse_iterator;
|
||||
using const_reverse_iterator = RegionToScopMapTy::const_reverse_iterator;
|
||||
using iterator = RegionToScopMapTy::iterator;
|
||||
using const_iterator = RegionToScopMapTy::const_iterator;
|
||||
|
||||
private:
|
||||
/// A map of Region to its Scop object containing
|
||||
/// Polly IR of static control part.
|
||||
RegionToScopMapTy RegionToScopMap;
|
||||
llvm::SmallDenseMap<const Region *, std::unique_ptr<Scop>> RegionToScopMap;
|
||||
const DataLayout &DL;
|
||||
ScopDetection &SD;
|
||||
ScalarEvolution &SE;
|
||||
@ -2701,47 +2694,12 @@ public:
|
||||
/// the scop object. If the given region is a subregion, return a
|
||||
/// nullptr. Top level region containing the entry block of a function
|
||||
/// is not considered in the scop creation.
|
||||
Scop *getScop(Region *R) const {
|
||||
auto MapIt = RegionToScopMap.find(R);
|
||||
if (MapIt != RegionToScopMap.end())
|
||||
return MapIt->second.get();
|
||||
return nullptr;
|
||||
}
|
||||
Scop *getScop(const Region *R);
|
||||
|
||||
/// Recompute the Scop-Information for a function.
|
||||
///
|
||||
/// This invalidates any iterators.
|
||||
void recompute();
|
||||
|
||||
/// Handle invalidation explicitly
|
||||
bool invalidate(Function &F, const PreservedAnalyses &PA,
|
||||
FunctionAnalysisManager::Invalidator &Inv);
|
||||
|
||||
iterator begin() { return RegionToScopMap.begin(); }
|
||||
iterator end() { return RegionToScopMap.end(); }
|
||||
const_iterator begin() const { return RegionToScopMap.begin(); }
|
||||
const_iterator end() const { return RegionToScopMap.end(); }
|
||||
reverse_iterator rbegin() { return RegionToScopMap.rbegin(); }
|
||||
reverse_iterator rend() { return RegionToScopMap.rend(); }
|
||||
const_reverse_iterator rbegin() const { return RegionToScopMap.rbegin(); }
|
||||
const_reverse_iterator rend() const { return RegionToScopMap.rend(); }
|
||||
bool empty() const { return RegionToScopMap.empty(); }
|
||||
};
|
||||
|
||||
struct ScopInfoAnalysis : AnalysisInfoMixin<ScopInfoAnalysis> {
|
||||
static AnalysisKey Key;
|
||||
|
||||
using Result = ScopInfo;
|
||||
|
||||
Result run(Function &, FunctionAnalysisManager &);
|
||||
};
|
||||
|
||||
struct ScopInfoPrinterPass final : PassInfoMixin<ScopInfoPrinterPass> {
|
||||
ScopInfoPrinterPass(raw_ostream &OS) : Stream(OS) {}
|
||||
|
||||
PreservedAnalyses run(Function &, FunctionAnalysisManager &);
|
||||
|
||||
raw_ostream &Stream;
|
||||
void invalidate();
|
||||
};
|
||||
} // end namespace polly
|
||||
|
||||
|
||||
@ -2579,73 +2579,30 @@ void updateLoopCountStatistic(ScopDetection::LoopStats Stats,
|
||||
ScopInfo::ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE,
|
||||
LoopInfo &LI, AliasAnalysis &AA, DominatorTree &DT,
|
||||
AssumptionCache &AC, OptimizationRemarkEmitter &ORE)
|
||||
: DL(DL), SD(SD), SE(SE), LI(LI), AA(AA), DT(DT), AC(AC), ORE(ORE) {
|
||||
recompute();
|
||||
}
|
||||
: DL(DL), SD(SD), SE(SE), LI(LI), AA(AA), DT(DT), AC(AC), ORE(ORE) {}
|
||||
|
||||
void ScopInfo::recompute() {
|
||||
RegionToScopMap.clear();
|
||||
/// Create polyhedral description of scops for all the valid regions of a
|
||||
/// function.
|
||||
for (auto &It : SD) {
|
||||
Region *R = const_cast<Region *>(It);
|
||||
if (!SD.isMaxRegionInScop(*R))
|
||||
continue;
|
||||
Scop *ScopInfo::getScop(const Region *R) {
|
||||
auto &&[It, Inserted] = RegionToScopMap.try_emplace(R);
|
||||
if (Inserted && SD.isMaxRegionInScop(*R)) {
|
||||
ScopBuilder SB(const_cast<Region *>(R), AC, AA, DL, DT, LI, SD, SE, ORE);
|
||||
It->second = SB.getScop();
|
||||
Scop *S = It->second.get();
|
||||
|
||||
ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE);
|
||||
std::unique_ptr<Scop> S = SB.getScop();
|
||||
if (!S)
|
||||
continue;
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
|
||||
ScopDetection::LoopStats Stats =
|
||||
ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0);
|
||||
updateLoopCountStatistic(Stats, S->getStatistics());
|
||||
if (S) {
|
||||
ScopDetection::LoopStats Stats =
|
||||
ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0);
|
||||
updateLoopCountStatistic(Stats, S->getStatistics());
|
||||
}
|
||||
#endif
|
||||
bool Inserted = RegionToScopMap.insert({R, std::move(S)}).second;
|
||||
assert(Inserted && "Building Scop for the same region twice!");
|
||||
(void)Inserted;
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
return It->second.get();
|
||||
}
|
||||
|
||||
bool ScopInfo::invalidate(Function &F, const PreservedAnalyses &PA,
|
||||
FunctionAnalysisManager::Invalidator &Inv) {
|
||||
// Check whether the analysis, all analyses on functions have been preserved
|
||||
// or anything we're holding references to is being invalidated
|
||||
auto PAC = PA.getChecker<ScopInfoAnalysis>();
|
||||
return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) ||
|
||||
Inv.invalidate<ScopAnalysis>(F, PA) ||
|
||||
Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) ||
|
||||
Inv.invalidate<LoopAnalysis>(F, PA) ||
|
||||
Inv.invalidate<AAManager>(F, PA) ||
|
||||
Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
|
||||
Inv.invalidate<AssumptionAnalysis>(F, PA);
|
||||
}
|
||||
|
||||
AnalysisKey ScopInfoAnalysis::Key;
|
||||
|
||||
ScopInfoAnalysis::Result ScopInfoAnalysis::run(Function &F,
|
||||
FunctionAnalysisManager &FAM) {
|
||||
auto &SD = FAM.getResult<ScopAnalysis>(F);
|
||||
auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
|
||||
auto &LI = FAM.getResult<LoopAnalysis>(F);
|
||||
auto &AA = FAM.getResult<AAManager>(F);
|
||||
auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
|
||||
auto &AC = FAM.getResult<AssumptionAnalysis>(F);
|
||||
auto &DL = F.getParent()->getDataLayout();
|
||||
auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
|
||||
return {DL, SD, SE, LI, AA, DT, AC, ORE};
|
||||
}
|
||||
|
||||
PreservedAnalyses ScopInfoPrinterPass::run(Function &F,
|
||||
FunctionAnalysisManager &FAM) {
|
||||
auto &SI = FAM.getResult<ScopInfoAnalysis>(F);
|
||||
// Since the legacy PM processes Scops in bottom up, we print them in reverse
|
||||
// order here to keep the output persistent
|
||||
for (auto &It : reverse(SI)) {
|
||||
if (It.second)
|
||||
It.second->print(Stream, PollyPrintInstructions);
|
||||
else
|
||||
Stream << "Invalid Scop!\n";
|
||||
}
|
||||
return PreservedAnalyses::all();
|
||||
void ScopInfo::invalidate() {
|
||||
// Recompute all SCoPs on-demand
|
||||
RegionToScopMap.clear();
|
||||
}
|
||||
|
||||
@ -156,18 +156,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
SmallPriorityWorklist<Region *, 4> Worklist;
|
||||
for (auto &[R, S] : Info)
|
||||
if (S)
|
||||
Worklist.insert(R);
|
||||
SmallPriorityWorklist<const Region *, 4> Worklist;
|
||||
for (const Region *R : SD)
|
||||
Worklist.insert(R);
|
||||
|
||||
TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
|
||||
while (!Worklist.empty()) {
|
||||
Region *R = Worklist.pop_back_val();
|
||||
const Region *R = Worklist.pop_back_val();
|
||||
Scop *S = Info.getScop(R);
|
||||
if (!S) {
|
||||
// This can happen if codegenning of a previous SCoP made this region
|
||||
// not-a-SCoP anymore.
|
||||
// This can happen if the region is not maximal, is not determined a
|
||||
// valid SCoP by ScopBuilder, or codegenning of a previous SCoP made
|
||||
// this region not-a-SCoP anymore.
|
||||
POLLY_DEBUG(dbgs() << "SCoP in Region '" << *R << "' disappeared");
|
||||
continue;
|
||||
}
|
||||
@ -253,10 +253,10 @@ public:
|
||||
if (ModifiedByCodeGen) {
|
||||
ModifiedIR = true;
|
||||
|
||||
// For all regions, create new polly::Scop objects because the old ones
|
||||
// refere to invalidated LLVM-IR.
|
||||
// FIXME: Adds all SCoPs again to statistics
|
||||
Info.recompute();
|
||||
// Discard old polly::Scop objects because they may refer to invalidated
|
||||
// LLVM-IR instructions and SCEV expressions. ScopInfo will recreate
|
||||
// them on demand.
|
||||
Info.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user