From 00b675df7357fafde1a1132f354ecaf80da205b4 Mon Sep 17 00:00:00 2001 From: Adam Nemet Date: Tue, 14 Jul 2015 22:32:50 +0000 Subject: [PATCH] [LAA] Introduce RuntimePointerChecking::PointerInfo, NFC Turn this structure-of-arrays (i.e. the various pointer attributes) into array-of-structures. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242219 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/LoopAccessAnalysis.h | 55 +++++++++++++++----------- lib/Analysis/LoopAccessAnalysis.cpp | 62 ++++++++++++++++-------------- lib/Transforms/Scalar/LoopDistribute.cpp | 4 +- 3 files changed, 67 insertions(+), 54 deletions(-) diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index cfd75dcd8c8..4e23e459fc6 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -295,18 +295,37 @@ private: /// This struct holds information about the memory runtime legality check that /// a group of pointers do not overlap. struct RuntimePointerChecking { + struct PointerInfo { + /// Holds the pointer value that we need to check. + TrackingVH PointerValue; + /// Holds the pointer value at the beginning of the loop. + const SCEV *Start; + /// Holds the pointer value at the end of the loop. + const SCEV *End; + /// Holds the information if this pointer is used for writing to memory. + bool IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + unsigned DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + unsigned AliasSetId; + /// SCEV for the access. + const SCEV *Expr; + + PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End, + bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId, + const SCEV *Expr) + : PointerValue(PointerValue), Start(Start), End(End), + IsWritePtr(IsWritePtr), DependencySetId(DependencySetId), + AliasSetId(AliasSetId), Expr(Expr) {} + }; + RuntimePointerChecking(ScalarEvolution *SE) : Need(false), SE(SE) {} /// Reset the state of the pointer runtime information. void reset() { Need = false; Pointers.clear(); - Starts.clear(); - Ends.clear(); - IsWritePtr.clear(); - DependencySetId.clear(); - AliasSetId.clear(); - Exprs.clear(); } /// Insert a pointer and calculate the start and end SCEVs. @@ -322,8 +341,8 @@ struct RuntimePointerChecking { /// \brief Create a new pointer checking group containing a single /// pointer, with index \p Index in RtCheck. CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck) - : RtCheck(RtCheck), High(RtCheck.Ends[Index]), - Low(RtCheck.Starts[Index]) { + : RtCheck(RtCheck), High(RtCheck.Pointers[Index].End), + Low(RtCheck.Pointers[Index].Start) { Members.push_back(Index); } @@ -387,23 +406,13 @@ struct RuntimePointerChecking { /// This flag indicates if we need to add the runtime check. bool Need; - /// Holds the pointers that we need to check. - SmallVector, 2> Pointers; - /// Holds the pointer value at the beginning of the loop. - SmallVector Starts; - /// Holds the pointer value at the end of the loop. - SmallVector Ends; - /// Holds the information if this pointer is used for writing to memory. - SmallVector IsWritePtr; - /// Holds the id of the set of pointers that could be dependent because of a - /// shared underlying object. - SmallVector DependencySetId; - /// Holds the id of the disjoint alias set to which this pointer belongs. - SmallVector AliasSetId; - /// Holds at position i the SCEV for the access i - SmallVector Exprs; + + /// Information about the pointers that may require checking. + SmallVector Pointers; + /// Holds a partitioning of pointers into "check groups". SmallVector CheckingGroups; + /// Holds a pointer to the ScalarEvolution analysis. ScalarEvolution *SE; }; diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp index db7f74264c1..becbae4c5b5 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -128,13 +128,8 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr, assert(AR && "Invalid addrec expression"); const SCEV *Ex = SE->getBackedgeTakenCount(Lp); const SCEV *ScEnd = AR->evaluateAtIteration(Ex, *SE); - Pointers.push_back(Ptr); - Starts.push_back(AR->getStart()); - Ends.push_back(ScEnd); - IsWritePtr.push_back(WritePtr); - DependencySetId.push_back(DepSetId); - AliasSetId.push_back(ASId); - Exprs.push_back(Sc); + Pointers.emplace_back(Ptr, AR->getStart(), ScEnd, WritePtr, DepSetId, ASId, + Sc); } bool RuntimePointerChecking::needsChecking( @@ -162,24 +157,27 @@ static const SCEV *getMinFromExprs(const SCEV *I, const SCEV *J, } bool RuntimePointerChecking::CheckingPtrGroup::addPointer(unsigned Index) { + const SCEV *Start = RtCheck.Pointers[Index].Start; + const SCEV *End = RtCheck.Pointers[Index].End; + // Compare the starts and ends with the known minimum and maximum // of this set. We need to know how we compare against the min/max // of the set in order to be able to emit memchecks. - const SCEV *Min0 = getMinFromExprs(RtCheck.Starts[Index], Low, RtCheck.SE); + const SCEV *Min0 = getMinFromExprs(Start, Low, RtCheck.SE); if (!Min0) return false; - const SCEV *Min1 = getMinFromExprs(RtCheck.Ends[Index], High, RtCheck.SE); + const SCEV *Min1 = getMinFromExprs(End, High, RtCheck.SE); if (!Min1) return false; // Update the low bound expression if we've found a new min value. - if (Min0 == RtCheck.Starts[Index]) - Low = RtCheck.Starts[Index]; + if (Min0 == Start) + Low = Start; // Update the high bound expression if we've found a new max value. - if (Min1 != RtCheck.Ends[Index]) - High = RtCheck.Ends[Index]; + if (Min1 != End) + High = End; Members.push_back(Index); return true; @@ -217,8 +215,8 @@ void RuntimePointerChecking::groupChecks( unsigned TotalComparisons = 0; DenseMap PositionMap; - for (unsigned Pointer = 0; Pointer < Pointers.size(); ++Pointer) - PositionMap[Pointers[Pointer]] = Pointer; + for (unsigned Index = 0; Index < Pointers.size(); ++Index) + PositionMap[Pointers[Index].PointerValue] = Index; // We need to keep track of what pointers we've already seen so we // don't process them twice. @@ -233,7 +231,8 @@ void RuntimePointerChecking::groupChecks( if (Seen.count(I)) continue; - MemoryDepChecker::MemAccessInfo Access(Pointers[I], IsWritePtr[I]); + MemoryDepChecker::MemAccessInfo Access(Pointers[I].PointerValue, + Pointers[I].IsWritePtr); SmallVector Groups; auto LeaderI = DepCands.findValue(DepCands.getLeaderValue(Access)); @@ -283,16 +282,19 @@ void RuntimePointerChecking::groupChecks( bool RuntimePointerChecking::needsChecking( unsigned I, unsigned J, const SmallVectorImpl *PtrPartition) const { + const PointerInfo &PointerI = Pointers[I]; + const PointerInfo &PointerJ = Pointers[J]; + // No need to check if two readonly pointers intersect. - if (!IsWritePtr[I] && !IsWritePtr[J]) + if (!PointerI.IsWritePtr && !PointerJ.IsWritePtr) return false; // Only need to check pointers between two different dependency sets. - if (DependencySetId[I] == DependencySetId[J]) + if (PointerI.DependencySetId == PointerJ.DependencySetId) return false; // Only need to check pointers in the same alias set. - if (AliasSetId[I] != AliasSetId[J]) + if (PointerI.AliasSetId != PointerJ.AliasSetId) return false; // If PtrPartition is set omit checks between pointers of the same partition. @@ -319,8 +321,8 @@ void RuntimePointerChecking::print( OS.indent(Depth + 2) << "Comparing group " << I << ":\n"; for (unsigned K = 0; K < CheckingGroups[I].Members.size(); ++K) { - OS.indent(Depth + 2) << *Pointers[CheckingGroups[I].Members[K]] - << "\n"; + OS.indent(Depth + 2) + << *Pointers[CheckingGroups[I].Members[K]].PointerValue << "\n"; if (PtrPartition) OS << " (Partition: " << (*PtrPartition)[CheckingGroups[I].Members[K]] << ")" @@ -330,8 +332,8 @@ void RuntimePointerChecking::print( OS.indent(Depth + 2) << "Against group " << J << ":\n"; for (unsigned K = 0; K < CheckingGroups[J].Members.size(); ++K) { - OS.indent(Depth + 2) << *Pointers[CheckingGroups[J].Members[K]] - << "\n"; + OS.indent(Depth + 2) + << *Pointers[CheckingGroups[J].Members[K]].PointerValue << "\n"; if (PtrPartition) OS << " (Partition: " << (*PtrPartition)[CheckingGroups[J].Members[K]] << ")" @@ -345,7 +347,8 @@ void RuntimePointerChecking::print( OS.indent(Depth + 4) << "(Low: " << *CheckingGroups[I].Low << " High: " << *CheckingGroups[I].High << ")\n"; for (unsigned J = 0; J < CheckingGroups[I].Members.size(); ++J) { - OS.indent(Depth + 6) << "Member: " << *Exprs[CheckingGroups[I].Members[J]] + OS.indent(Depth + 6) << "Member: " + << *Pointers[CheckingGroups[I].Members[J]].Expr << "\n"; } } @@ -575,14 +578,15 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck, for (unsigned i = 0; i < NumPointers; ++i) { for (unsigned j = i + 1; j < NumPointers; ++j) { // Only need to check pointers between two different dependency sets. - if (RtCheck.DependencySetId[i] == RtCheck.DependencySetId[j]) + if (RtCheck.Pointers[i].DependencySetId == + RtCheck.Pointers[j].DependencySetId) continue; // Only need to check pointers in the same alias set. - if (RtCheck.AliasSetId[i] != RtCheck.AliasSetId[j]) + if (RtCheck.Pointers[i].AliasSetId != RtCheck.Pointers[j].AliasSetId) continue; - Value *PtrI = RtCheck.Pointers[i]; - Value *PtrJ = RtCheck.Pointers[j]; + Value *PtrI = RtCheck.Pointers[i].PointerValue; + Value *PtrJ = RtCheck.Pointers[j].PointerValue; unsigned ASi = PtrI->getType()->getPointerAddressSpace(); unsigned ASj = PtrJ->getType()->getPointerAddressSpace(); @@ -1577,7 +1581,7 @@ std::pair LoopAccessInfo::addRuntimeCheck( for (unsigned i = 0; i < PtrRtChecking.CheckingGroups.size(); ++i) { const RuntimePointerChecking::CheckingPtrGroup &CG = PtrRtChecking.CheckingGroups[i]; - Value *Ptr = PtrRtChecking.Pointers[CG.Members[0]]; + Value *Ptr = PtrRtChecking.Pointers[CG.Members[0]].PointerValue; const SCEV *Sc = SE->getSCEV(Ptr); if (SE->isLoopInvariant(Sc, TheLoop)) { diff --git a/lib/Transforms/Scalar/LoopDistribute.cpp b/lib/Transforms/Scalar/LoopDistribute.cpp index 3380af29ca8..1b9859b5779 100644 --- a/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/lib/Transforms/Scalar/LoopDistribute.cpp @@ -437,9 +437,9 @@ public: unsigned N = RtPtrCheck->Pointers.size(); SmallVector PtrToPartitions(N); for (unsigned I = 0; I < N; ++I) { - Value *Ptr = RtPtrCheck->Pointers[I]; + Value *Ptr = RtPtrCheck->Pointers[I].PointerValue; auto Instructions = - LAI.getInstructionsForAccess(Ptr, RtPtrCheck->IsWritePtr[I]); + LAI.getInstructionsForAccess(Ptr, RtPtrCheck->Pointers[I].IsWritePtr); int &Partition = PtrToPartitions[I]; // First set it to uninitialized. -- 2.11.0