forked from OSchip/llvm-project
[LoopDist] Split main class. NFC
This splits out the per-loop functionality from the Pass class. With this the fact whether the loop is forced-distribute with the new metadata/pragma can be cached in the per-loop class rather than passed around. llvm-svn: 267643
This commit is contained in:
parent
3f83dbeed9
commit
61399ac424
|
@ -571,92 +571,15 @@ private:
|
|||
AccessesType Accesses;
|
||||
};
|
||||
|
||||
/// \brief The pass class.
|
||||
class LoopDistribute : public FunctionPass {
|
||||
/// \brief The actual class performing the per-loop work.
|
||||
class LoopDistributeForLoop {
|
||||
public:
|
||||
LoopDistribute() : FunctionPass(ID) {
|
||||
initializeLoopDistributePass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F) override {
|
||||
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
LAA = &getAnalysis<LoopAccessAnalysis>();
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
|
||||
// Build up a worklist of inner-loops to vectorize. This is necessary as the
|
||||
// act of distributing a loop creates new loops and can invalidate iterators
|
||||
// across the loops.
|
||||
SmallVector<Loop *, 8> Worklist;
|
||||
|
||||
for (Loop *TopLevelLoop : *LI)
|
||||
for (Loop *L : depth_first(TopLevelLoop))
|
||||
// We only handle inner-most loops.
|
||||
if (L->empty())
|
||||
Worklist.push_back(L);
|
||||
|
||||
// Now walk the identified inner loops.
|
||||
bool Changed = false;
|
||||
for (Loop *L : Worklist)
|
||||
Changed |= processLoop(L);
|
||||
|
||||
// Process each loop nest in the function.
|
||||
return Changed;
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addPreserved<LoopInfoWrapperPass>();
|
||||
AU.addRequired<LoopAccessAnalysis>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
}
|
||||
|
||||
static char ID;
|
||||
|
||||
private:
|
||||
/// \brief Filter out checks between pointers from the same partition.
|
||||
///
|
||||
/// \p PtrToPartition contains the partition number for pointers. Partition
|
||||
/// number -1 means that the pointer is used in multiple partitions. In this
|
||||
/// case we can't safely omit the check.
|
||||
SmallVector<RuntimePointerChecking::PointerCheck, 4>
|
||||
includeOnlyCrossPartitionChecks(
|
||||
const SmallVectorImpl<RuntimePointerChecking::PointerCheck> &AllChecks,
|
||||
const SmallVectorImpl<int> &PtrToPartition,
|
||||
const RuntimePointerChecking *RtPtrChecking) {
|
||||
SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks;
|
||||
|
||||
std::copy_if(AllChecks.begin(), AllChecks.end(), std::back_inserter(Checks),
|
||||
[&](const RuntimePointerChecking::PointerCheck &Check) {
|
||||
for (unsigned PtrIdx1 : Check.first->Members)
|
||||
for (unsigned PtrIdx2 : Check.second->Members)
|
||||
// Only include this check if there is a pair of pointers
|
||||
// that require checking and the pointers fall into
|
||||
// separate partitions.
|
||||
//
|
||||
// (Note that we already know at this point that the two
|
||||
// pointer groups need checking but it doesn't follow
|
||||
// that each pair of pointers within the two groups need
|
||||
// checking as well.
|
||||
//
|
||||
// In other words we don't want to include a check just
|
||||
// because there is a pair of pointers between the two
|
||||
// pointer groups that require checks and a different
|
||||
// pair whose pointers fall into different partitions.)
|
||||
if (RtPtrChecking->needsChecking(PtrIdx1, PtrIdx2) &&
|
||||
!RuntimePointerChecking::arePointersInSamePartition(
|
||||
PtrToPartition, PtrIdx1, PtrIdx2))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
return Checks;
|
||||
}
|
||||
LoopDistributeForLoop(Loop *L, LoopInfo *LI, const LoopAccessInfo &LAI,
|
||||
DominatorTree *DT, ScalarEvolution *SE)
|
||||
: L(L), LI(LI), LAI(LAI), DT(DT), SE(SE) {}
|
||||
|
||||
/// \brief Try to distribute an inner-most loop.
|
||||
bool processLoop(Loop *L) {
|
||||
bool processLoop() {
|
||||
assert(L->empty() && "Only process inner loops.");
|
||||
|
||||
DEBUG(dbgs() << "\nLDist: In \"" << L->getHeader()->getParent()->getName()
|
||||
|
@ -673,8 +596,6 @@ private:
|
|||
}
|
||||
// LAA will check that we only have a single exiting block.
|
||||
|
||||
const LoopAccessInfo &LAI = LAA->getInfo(L, ValueToValueMap());
|
||||
|
||||
// Currently, we only distribute to isolate the part of the loop with
|
||||
// dependence cycles to enable partial vectorization.
|
||||
if (LAI.canVectorizeMemory()) {
|
||||
|
@ -814,12 +735,101 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief Filter out checks between pointers from the same partition.
|
||||
///
|
||||
/// \p PtrToPartition contains the partition number for pointers. Partition
|
||||
/// number -1 means that the pointer is used in multiple partitions. In this
|
||||
/// case we can't safely omit the check.
|
||||
SmallVector<RuntimePointerChecking::PointerCheck, 4>
|
||||
includeOnlyCrossPartitionChecks(
|
||||
const SmallVectorImpl<RuntimePointerChecking::PointerCheck> &AllChecks,
|
||||
const SmallVectorImpl<int> &PtrToPartition,
|
||||
const RuntimePointerChecking *RtPtrChecking) {
|
||||
SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks;
|
||||
|
||||
std::copy_if(AllChecks.begin(), AllChecks.end(), std::back_inserter(Checks),
|
||||
[&](const RuntimePointerChecking::PointerCheck &Check) {
|
||||
for (unsigned PtrIdx1 : Check.first->Members)
|
||||
for (unsigned PtrIdx2 : Check.second->Members)
|
||||
// Only include this check if there is a pair of pointers
|
||||
// that require checking and the pointers fall into
|
||||
// separate partitions.
|
||||
//
|
||||
// (Note that we already know at this point that the two
|
||||
// pointer groups need checking but it doesn't follow
|
||||
// that each pair of pointers within the two groups need
|
||||
// checking as well.
|
||||
//
|
||||
// In other words we don't want to include a check just
|
||||
// because there is a pair of pointers between the two
|
||||
// pointer groups that require checks and a different
|
||||
// pair whose pointers fall into different partitions.)
|
||||
if (RtPtrChecking->needsChecking(PtrIdx1, PtrIdx2) &&
|
||||
!RuntimePointerChecking::arePointersInSamePartition(
|
||||
PtrToPartition, PtrIdx1, PtrIdx2))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
return Checks;
|
||||
}
|
||||
|
||||
// Analyses used.
|
||||
Loop *L;
|
||||
LoopInfo *LI;
|
||||
LoopAccessAnalysis *LAA;
|
||||
const LoopAccessInfo &LAI;
|
||||
DominatorTree *DT;
|
||||
ScalarEvolution *SE;
|
||||
};
|
||||
|
||||
/// \brief The pass class.
|
||||
class LoopDistribute : public FunctionPass {
|
||||
public:
|
||||
LoopDistribute() : FunctionPass(ID) {
|
||||
initializeLoopDistributePass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F) override {
|
||||
auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
auto *LAA = &getAnalysis<LoopAccessAnalysis>();
|
||||
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
|
||||
// Build up a worklist of inner-loops to vectorize. This is necessary as the
|
||||
// act of distributing a loop creates new loops and can invalidate iterators
|
||||
// across the loops.
|
||||
SmallVector<Loop *, 8> Worklist;
|
||||
|
||||
for (Loop *TopLevelLoop : *LI)
|
||||
for (Loop *L : depth_first(TopLevelLoop))
|
||||
// We only handle inner-most loops.
|
||||
if (L->empty())
|
||||
Worklist.push_back(L);
|
||||
|
||||
// Now walk the identified inner loops.
|
||||
bool Changed = false;
|
||||
for (Loop *L : Worklist) {
|
||||
const LoopAccessInfo &LAI = LAA->getInfo(L, ValueToValueMap());
|
||||
LoopDistributeForLoop LDL(L, LI, LAI, DT, SE);
|
||||
Changed |= LDL.processLoop();
|
||||
}
|
||||
|
||||
// Process each loop nest in the function.
|
||||
return Changed;
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addPreserved<LoopInfoWrapperPass>();
|
||||
AU.addRequired<LoopAccessAnalysis>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
}
|
||||
|
||||
static char ID;
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
char LoopDistribute::ID;
|
||||
|
|
Loading…
Reference in New Issue