From 61399ac424373662b72515e1c47b799c8204536f Mon Sep 17 00:00:00 2001 From: Adam Nemet Date: Wed, 27 Apr 2016 00:31:03 +0000 Subject: [PATCH] [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 --- llvm/lib/Transforms/Scalar/LoopDistribute.cpp | 182 ++++++++++++++------------ 1 file changed, 96 insertions(+), 86 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp index 7cd6ea9..196bec2 100644 --- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp @@ -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().getLoopInfo(); - LAA = &getAnalysis(); - DT = &getAnalysis().getDomTree(); - SE = &getAnalysis().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 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(); - AU.addRequired(); - AU.addPreserved(); - AU.addRequired(); - AU.addRequired(); - AU.addPreserved(); - } - - 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 - includeOnlyCrossPartitionChecks( - const SmallVectorImpl &AllChecks, - const SmallVectorImpl &PtrToPartition, - const RuntimePointerChecking *RtPtrChecking) { - SmallVector 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 + includeOnlyCrossPartitionChecks( + const SmallVectorImpl &AllChecks, + const SmallVectorImpl &PtrToPartition, + const RuntimePointerChecking *RtPtrChecking) { + SmallVector 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().getLoopInfo(); + auto *LAA = &getAnalysis(); + auto *DT = &getAnalysis().getDomTree(); + auto *SE = &getAnalysis().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 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(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + } + + static char ID; +}; } // anonymous namespace char LoopDistribute::ID; -- 2.7.4