mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-20 05:38:50 +00:00
[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
This commit is contained in:
parent
944e082905
commit
00b675df73
@ -295,18 +295,37 @@ private:
|
|||||||
/// This struct holds information about the memory runtime legality check that
|
/// This struct holds information about the memory runtime legality check that
|
||||||
/// a group of pointers do not overlap.
|
/// a group of pointers do not overlap.
|
||||||
struct RuntimePointerChecking {
|
struct RuntimePointerChecking {
|
||||||
|
struct PointerInfo {
|
||||||
|
/// Holds the pointer value that we need to check.
|
||||||
|
TrackingVH<Value> 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) {}
|
RuntimePointerChecking(ScalarEvolution *SE) : Need(false), SE(SE) {}
|
||||||
|
|
||||||
/// Reset the state of the pointer runtime information.
|
/// Reset the state of the pointer runtime information.
|
||||||
void reset() {
|
void reset() {
|
||||||
Need = false;
|
Need = false;
|
||||||
Pointers.clear();
|
Pointers.clear();
|
||||||
Starts.clear();
|
|
||||||
Ends.clear();
|
|
||||||
IsWritePtr.clear();
|
|
||||||
DependencySetId.clear();
|
|
||||||
AliasSetId.clear();
|
|
||||||
Exprs.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a pointer and calculate the start and end SCEVs.
|
/// 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
|
/// \brief Create a new pointer checking group containing a single
|
||||||
/// pointer, with index \p Index in RtCheck.
|
/// pointer, with index \p Index in RtCheck.
|
||||||
CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck)
|
CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck)
|
||||||
: RtCheck(RtCheck), High(RtCheck.Ends[Index]),
|
: RtCheck(RtCheck), High(RtCheck.Pointers[Index].End),
|
||||||
Low(RtCheck.Starts[Index]) {
|
Low(RtCheck.Pointers[Index].Start) {
|
||||||
Members.push_back(Index);
|
Members.push_back(Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,23 +406,13 @@ struct RuntimePointerChecking {
|
|||||||
|
|
||||||
/// This flag indicates if we need to add the runtime check.
|
/// This flag indicates if we need to add the runtime check.
|
||||||
bool Need;
|
bool Need;
|
||||||
/// Holds the pointers that we need to check.
|
|
||||||
SmallVector<TrackingVH<Value>, 2> Pointers;
|
/// Information about the pointers that may require checking.
|
||||||
/// Holds the pointer value at the beginning of the loop.
|
SmallVector<PointerInfo, 2> Pointers;
|
||||||
SmallVector<const SCEV *, 2> Starts;
|
|
||||||
/// Holds the pointer value at the end of the loop.
|
|
||||||
SmallVector<const SCEV *, 2> Ends;
|
|
||||||
/// Holds the information if this pointer is used for writing to memory.
|
|
||||||
SmallVector<bool, 2> IsWritePtr;
|
|
||||||
/// Holds the id of the set of pointers that could be dependent because of a
|
|
||||||
/// shared underlying object.
|
|
||||||
SmallVector<unsigned, 2> DependencySetId;
|
|
||||||
/// Holds the id of the disjoint alias set to which this pointer belongs.
|
|
||||||
SmallVector<unsigned, 2> AliasSetId;
|
|
||||||
/// Holds at position i the SCEV for the access i
|
|
||||||
SmallVector<const SCEV *, 2> Exprs;
|
|
||||||
/// Holds a partitioning of pointers into "check groups".
|
/// Holds a partitioning of pointers into "check groups".
|
||||||
SmallVector<CheckingPtrGroup, 2> CheckingGroups;
|
SmallVector<CheckingPtrGroup, 2> CheckingGroups;
|
||||||
|
|
||||||
/// Holds a pointer to the ScalarEvolution analysis.
|
/// Holds a pointer to the ScalarEvolution analysis.
|
||||||
ScalarEvolution *SE;
|
ScalarEvolution *SE;
|
||||||
};
|
};
|
||||||
|
@ -128,13 +128,8 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr,
|
|||||||
assert(AR && "Invalid addrec expression");
|
assert(AR && "Invalid addrec expression");
|
||||||
const SCEV *Ex = SE->getBackedgeTakenCount(Lp);
|
const SCEV *Ex = SE->getBackedgeTakenCount(Lp);
|
||||||
const SCEV *ScEnd = AR->evaluateAtIteration(Ex, *SE);
|
const SCEV *ScEnd = AR->evaluateAtIteration(Ex, *SE);
|
||||||
Pointers.push_back(Ptr);
|
Pointers.emplace_back(Ptr, AR->getStart(), ScEnd, WritePtr, DepSetId, ASId,
|
||||||
Starts.push_back(AR->getStart());
|
Sc);
|
||||||
Ends.push_back(ScEnd);
|
|
||||||
IsWritePtr.push_back(WritePtr);
|
|
||||||
DependencySetId.push_back(DepSetId);
|
|
||||||
AliasSetId.push_back(ASId);
|
|
||||||
Exprs.push_back(Sc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuntimePointerChecking::needsChecking(
|
bool RuntimePointerChecking::needsChecking(
|
||||||
@ -162,24 +157,27 @@ static const SCEV *getMinFromExprs(const SCEV *I, const SCEV *J,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RuntimePointerChecking::CheckingPtrGroup::addPointer(unsigned Index) {
|
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
|
// 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 this set. We need to know how we compare against the min/max
|
||||||
// of the set in order to be able to emit memchecks.
|
// 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)
|
if (!Min0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const SCEV *Min1 = getMinFromExprs(RtCheck.Ends[Index], High, RtCheck.SE);
|
const SCEV *Min1 = getMinFromExprs(End, High, RtCheck.SE);
|
||||||
if (!Min1)
|
if (!Min1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Update the low bound expression if we've found a new min value.
|
// Update the low bound expression if we've found a new min value.
|
||||||
if (Min0 == RtCheck.Starts[Index])
|
if (Min0 == Start)
|
||||||
Low = RtCheck.Starts[Index];
|
Low = Start;
|
||||||
|
|
||||||
// Update the high bound expression if we've found a new max value.
|
// Update the high bound expression if we've found a new max value.
|
||||||
if (Min1 != RtCheck.Ends[Index])
|
if (Min1 != End)
|
||||||
High = RtCheck.Ends[Index];
|
High = End;
|
||||||
|
|
||||||
Members.push_back(Index);
|
Members.push_back(Index);
|
||||||
return true;
|
return true;
|
||||||
@ -217,8 +215,8 @@ void RuntimePointerChecking::groupChecks(
|
|||||||
unsigned TotalComparisons = 0;
|
unsigned TotalComparisons = 0;
|
||||||
|
|
||||||
DenseMap<Value *, unsigned> PositionMap;
|
DenseMap<Value *, unsigned> PositionMap;
|
||||||
for (unsigned Pointer = 0; Pointer < Pointers.size(); ++Pointer)
|
for (unsigned Index = 0; Index < Pointers.size(); ++Index)
|
||||||
PositionMap[Pointers[Pointer]] = Pointer;
|
PositionMap[Pointers[Index].PointerValue] = Index;
|
||||||
|
|
||||||
// We need to keep track of what pointers we've already seen so we
|
// We need to keep track of what pointers we've already seen so we
|
||||||
// don't process them twice.
|
// don't process them twice.
|
||||||
@ -233,7 +231,8 @@ void RuntimePointerChecking::groupChecks(
|
|||||||
if (Seen.count(I))
|
if (Seen.count(I))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MemoryDepChecker::MemAccessInfo Access(Pointers[I], IsWritePtr[I]);
|
MemoryDepChecker::MemAccessInfo Access(Pointers[I].PointerValue,
|
||||||
|
Pointers[I].IsWritePtr);
|
||||||
|
|
||||||
SmallVector<CheckingPtrGroup, 2> Groups;
|
SmallVector<CheckingPtrGroup, 2> Groups;
|
||||||
auto LeaderI = DepCands.findValue(DepCands.getLeaderValue(Access));
|
auto LeaderI = DepCands.findValue(DepCands.getLeaderValue(Access));
|
||||||
@ -283,16 +282,19 @@ void RuntimePointerChecking::groupChecks(
|
|||||||
|
|
||||||
bool RuntimePointerChecking::needsChecking(
|
bool RuntimePointerChecking::needsChecking(
|
||||||
unsigned I, unsigned J, const SmallVectorImpl<int> *PtrPartition) const {
|
unsigned I, unsigned J, const SmallVectorImpl<int> *PtrPartition) const {
|
||||||
|
const PointerInfo &PointerI = Pointers[I];
|
||||||
|
const PointerInfo &PointerJ = Pointers[J];
|
||||||
|
|
||||||
// No need to check if two readonly pointers intersect.
|
// No need to check if two readonly pointers intersect.
|
||||||
if (!IsWritePtr[I] && !IsWritePtr[J])
|
if (!PointerI.IsWritePtr && !PointerJ.IsWritePtr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Only need to check pointers between two different dependency sets.
|
// Only need to check pointers between two different dependency sets.
|
||||||
if (DependencySetId[I] == DependencySetId[J])
|
if (PointerI.DependencySetId == PointerJ.DependencySetId)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Only need to check pointers in the same alias set.
|
// Only need to check pointers in the same alias set.
|
||||||
if (AliasSetId[I] != AliasSetId[J])
|
if (PointerI.AliasSetId != PointerJ.AliasSetId)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If PtrPartition is set omit checks between pointers of the same partition.
|
// 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";
|
OS.indent(Depth + 2) << "Comparing group " << I << ":\n";
|
||||||
|
|
||||||
for (unsigned K = 0; K < CheckingGroups[I].Members.size(); ++K) {
|
for (unsigned K = 0; K < CheckingGroups[I].Members.size(); ++K) {
|
||||||
OS.indent(Depth + 2) << *Pointers[CheckingGroups[I].Members[K]]
|
OS.indent(Depth + 2)
|
||||||
<< "\n";
|
<< *Pointers[CheckingGroups[I].Members[K]].PointerValue << "\n";
|
||||||
if (PtrPartition)
|
if (PtrPartition)
|
||||||
OS << " (Partition: "
|
OS << " (Partition: "
|
||||||
<< (*PtrPartition)[CheckingGroups[I].Members[K]] << ")"
|
<< (*PtrPartition)[CheckingGroups[I].Members[K]] << ")"
|
||||||
@ -330,8 +332,8 @@ void RuntimePointerChecking::print(
|
|||||||
OS.indent(Depth + 2) << "Against group " << J << ":\n";
|
OS.indent(Depth + 2) << "Against group " << J << ":\n";
|
||||||
|
|
||||||
for (unsigned K = 0; K < CheckingGroups[J].Members.size(); ++K) {
|
for (unsigned K = 0; K < CheckingGroups[J].Members.size(); ++K) {
|
||||||
OS.indent(Depth + 2) << *Pointers[CheckingGroups[J].Members[K]]
|
OS.indent(Depth + 2)
|
||||||
<< "\n";
|
<< *Pointers[CheckingGroups[J].Members[K]].PointerValue << "\n";
|
||||||
if (PtrPartition)
|
if (PtrPartition)
|
||||||
OS << " (Partition: "
|
OS << " (Partition: "
|
||||||
<< (*PtrPartition)[CheckingGroups[J].Members[K]] << ")"
|
<< (*PtrPartition)[CheckingGroups[J].Members[K]] << ")"
|
||||||
@ -345,7 +347,8 @@ void RuntimePointerChecking::print(
|
|||||||
OS.indent(Depth + 4) << "(Low: " << *CheckingGroups[I].Low
|
OS.indent(Depth + 4) << "(Low: " << *CheckingGroups[I].Low
|
||||||
<< " High: " << *CheckingGroups[I].High << ")\n";
|
<< " High: " << *CheckingGroups[I].High << ")\n";
|
||||||
for (unsigned J = 0; J < CheckingGroups[I].Members.size(); ++J) {
|
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";
|
<< "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -575,14 +578,15 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
|
|||||||
for (unsigned i = 0; i < NumPointers; ++i) {
|
for (unsigned i = 0; i < NumPointers; ++i) {
|
||||||
for (unsigned j = i + 1; j < NumPointers; ++j) {
|
for (unsigned j = i + 1; j < NumPointers; ++j) {
|
||||||
// Only need to check pointers between two different dependency sets.
|
// 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;
|
continue;
|
||||||
// Only need to check pointers in the same alias set.
|
// 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;
|
continue;
|
||||||
|
|
||||||
Value *PtrI = RtCheck.Pointers[i];
|
Value *PtrI = RtCheck.Pointers[i].PointerValue;
|
||||||
Value *PtrJ = RtCheck.Pointers[j];
|
Value *PtrJ = RtCheck.Pointers[j].PointerValue;
|
||||||
|
|
||||||
unsigned ASi = PtrI->getType()->getPointerAddressSpace();
|
unsigned ASi = PtrI->getType()->getPointerAddressSpace();
|
||||||
unsigned ASj = PtrJ->getType()->getPointerAddressSpace();
|
unsigned ASj = PtrJ->getType()->getPointerAddressSpace();
|
||||||
@ -1577,7 +1581,7 @@ std::pair<Instruction *, Instruction *> LoopAccessInfo::addRuntimeCheck(
|
|||||||
for (unsigned i = 0; i < PtrRtChecking.CheckingGroups.size(); ++i) {
|
for (unsigned i = 0; i < PtrRtChecking.CheckingGroups.size(); ++i) {
|
||||||
const RuntimePointerChecking::CheckingPtrGroup &CG =
|
const RuntimePointerChecking::CheckingPtrGroup &CG =
|
||||||
PtrRtChecking.CheckingGroups[i];
|
PtrRtChecking.CheckingGroups[i];
|
||||||
Value *Ptr = PtrRtChecking.Pointers[CG.Members[0]];
|
Value *Ptr = PtrRtChecking.Pointers[CG.Members[0]].PointerValue;
|
||||||
const SCEV *Sc = SE->getSCEV(Ptr);
|
const SCEV *Sc = SE->getSCEV(Ptr);
|
||||||
|
|
||||||
if (SE->isLoopInvariant(Sc, TheLoop)) {
|
if (SE->isLoopInvariant(Sc, TheLoop)) {
|
||||||
|
@ -437,9 +437,9 @@ public:
|
|||||||
unsigned N = RtPtrCheck->Pointers.size();
|
unsigned N = RtPtrCheck->Pointers.size();
|
||||||
SmallVector<int, 8> PtrToPartitions(N);
|
SmallVector<int, 8> PtrToPartitions(N);
|
||||||
for (unsigned I = 0; I < N; ++I) {
|
for (unsigned I = 0; I < N; ++I) {
|
||||||
Value *Ptr = RtPtrCheck->Pointers[I];
|
Value *Ptr = RtPtrCheck->Pointers[I].PointerValue;
|
||||||
auto Instructions =
|
auto Instructions =
|
||||||
LAI.getInstructionsForAccess(Ptr, RtPtrCheck->IsWritePtr[I]);
|
LAI.getInstructionsForAccess(Ptr, RtPtrCheck->Pointers[I].IsWritePtr);
|
||||||
|
|
||||||
int &Partition = PtrToPartitions[I];
|
int &Partition = PtrToPartitions[I];
|
||||||
// First set it to uninitialized.
|
// First set it to uninitialized.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user