diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index d188327fbf4..0a9dc07102e 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -231,6 +231,10 @@ public: return InstMap; } + /// \brief Find the set of instructions that read or write via \p Ptr. + SmallVector getInstructionsForAccess(Value *Ptr, + bool isWrite) const; + private: ScalarEvolution *SE; const Loop *InnermostLoop; @@ -328,10 +332,20 @@ public: /// \brief Decide whether we need to issue a run-time check for pointer at /// index \p I and \p J to prove their independence. - bool needsChecking(unsigned I, unsigned J) const; + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + bool needsChecking(unsigned I, unsigned J, + const SmallVectorImpl *PtrPartition) const; /// \brief Print the list run-time memory checks necessary. - void print(raw_ostream &OS, unsigned Depth = 0) const; + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + void print(raw_ostream &OS, unsigned Depth = 0, + const SmallVectorImpl *PtrPartition = nullptr) const; /// This flag indicates if we need to add the runtime check. bool Need; @@ -383,8 +397,13 @@ public: /// Returns a pair of instructions where the first element is the first /// instruction generated in possibly a sequence of instructions and the /// second value is the final comparator value or NULL if no check is needed. + /// + /// If \p PtrPartition is set, it contains the partition number for pointers + /// (-1 if the pointer belongs to multiple partitions). In this case omit + /// checks between pointers belonging to the same partition. std::pair - addRuntimeCheck(Instruction *Loc) const; + addRuntimeCheck(Instruction *Loc, + const SmallVectorImpl *PtrPartition = nullptr) const; /// \brief The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. @@ -394,6 +413,13 @@ public: /// loop-independent and loop-carried dependences between memory accesses. const MemoryDepChecker &getDepChecker() const { return DepChecker; } + /// \brief Return the list of instructions that use \p Ptr to read or write + /// memory. + SmallVector getInstructionsForAccess(Value *Ptr, + bool isWrite) const { + return DepChecker.getInstructionsForAccess(Ptr, isWrite); + } + /// \brief Print the information about the memory accesses in the loop. void print(raw_ostream &OS, unsigned Depth = 0) const; diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp index d044bb008e9..4bedccf8d01 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -127,8 +127,8 @@ void LoopAccessInfo::RuntimePointerCheck::insert( AliasSetId.push_back(ASId); } -bool LoopAccessInfo::RuntimePointerCheck::needsChecking(unsigned I, - unsigned J) const { +bool LoopAccessInfo::RuntimePointerCheck::needsChecking( + unsigned I, unsigned J, const SmallVectorImpl *PtrPartition) const { // No need to check if two readonly pointers intersect. if (!IsWritePtr[I] && !IsWritePtr[J]) return false; @@ -141,11 +141,19 @@ bool LoopAccessInfo::RuntimePointerCheck::needsChecking(unsigned I, if (AliasSetId[I] != AliasSetId[J]) return false; + // If PtrPartition is set omit checks between pointers of the same partition. + // Partition number -1 means that the pointer is used in multiple partitions. + // In this case we can't omit the check. + if (PtrPartition && (*PtrPartition)[I] != -1 && + (*PtrPartition)[I] == (*PtrPartition)[J]) + return false; + return true; } -void LoopAccessInfo::RuntimePointerCheck::print(raw_ostream &OS, - unsigned Depth) const { +void LoopAccessInfo::RuntimePointerCheck::print( + raw_ostream &OS, unsigned Depth, + const SmallVectorImpl *PtrPartition) const { unsigned NumPointers = Pointers.size(); if (NumPointers == 0) return; @@ -154,10 +162,16 @@ void LoopAccessInfo::RuntimePointerCheck::print(raw_ostream &OS, unsigned N = 0; for (unsigned I = 0; I < NumPointers; ++I) for (unsigned J = I + 1; J < NumPointers; ++J) - if (needsChecking(I, J)) { + if (needsChecking(I, J, PtrPartition)) { OS.indent(Depth) << N++ << ":\n"; - OS.indent(Depth + 2) << *Pointers[I] << "\n"; - OS.indent(Depth + 2) << *Pointers[J] << "\n"; + OS.indent(Depth + 2) << *Pointers[I]; + if (PtrPartition) + OS << " (Partition: " << (*PtrPartition)[I] << ")"; + OS << "\n"; + OS.indent(Depth + 2) << *Pointers[J]; + if (PtrPartition) + OS << " (Partition: " << (*PtrPartition)[J] << ")"; + OS << "\n"; } } @@ -835,6 +849,18 @@ bool MemoryDepChecker::areDepsSafe(DepCandidates &AccessSets, return SafeForVectorization; } +SmallVector +MemoryDepChecker::getInstructionsForAccess(Value *Ptr, bool isWrite) const { + MemAccessInfo Access(Ptr, isWrite); + auto &IndexVector = Accesses.find(Access)->second; + + SmallVector Insts; + std::transform(IndexVector.begin(), IndexVector.end(), + std::back_inserter(Insts), + [&](unsigned Idx) { return this->InstMap[Idx]; }); + return Insts; +} + const char *MemoryDepChecker::Dependence::DepName[] = { "NoDep", "Unknown", "Forward", "ForwardButPreventsForwarding", "Backward", "BackwardVectorizable", "BackwardVectorizableButPreventsForwarding"}; @@ -1169,8 +1195,8 @@ static Instruction *getFirstInst(Instruction *FirstInst, Value *V, return nullptr; } -std::pair -LoopAccessInfo::addRuntimeCheck(Instruction *Loc) const { +std::pair LoopAccessInfo::addRuntimeCheck( + Instruction *Loc, const SmallVectorImpl *PtrPartition) const { Instruction *tnullptr = nullptr; if (!PtrRtCheck.Need) return std::pair(tnullptr, tnullptr); @@ -1211,7 +1237,7 @@ LoopAccessInfo::addRuntimeCheck(Instruction *Loc) const { Value *MemoryRuntimeCheck = nullptr; for (unsigned i = 0; i < NumPointers; ++i) { for (unsigned j = i+1; j < NumPointers; ++j) { - if (!PtrRtCheck.needsChecking(i, j)) + if (!PtrRtCheck.needsChecking(i, j, PtrPartition)) continue; unsigned AS0 = Starts[i]->getType()->getPointerAddressSpace();