summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/LoopAccessAnalysis.cpp51
1 files changed, 34 insertions, 17 deletions
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index e8f52eda3c4..4e076f5f004 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -1058,30 +1058,47 @@ static unsigned getAddressSpaceOperand(Value *I) {
return -1;
}
-/// Saves the memory accesses after sorting it into vector argument 'Sorted'.
void llvm::sortMemAccesses(ArrayRef<Value *> VL, const DataLayout &DL,
ScalarEvolution &SE,
SmallVectorImpl<Value *> &Sorted) {
- SmallVector<std::pair<int, Value *>, 4> OffValPairs;
+ SmallVector<std::pair<int64_t, Value *>, 4> OffValPairs;
+ OffValPairs.reserve(VL.size());
+ Sorted.reserve(VL.size());
+
+ // Walk over the pointers, and map each of them to an offset relative to
+ // first pointer in the array.
+ Value *Ptr0 = getPointerOperand(VL[0]);
+ const SCEV *Scev0 = SE.getSCEV(Ptr0);
+ Value *Obj0 = GetUnderlyingObject(Ptr0, DL);
+
for (auto *Val : VL) {
- // Compute the constant offset from the base pointer of each memory accesses
- // and insert into the vector of key,value pair which needs to be sorted.
Value *Ptr = getPointerOperand(Val);
- unsigned AS = getAddressSpaceOperand(Val);
- unsigned PtrBitWidth = DL.getPointerSizeInBits(AS);
- Type *Ty = cast<PointerType>(Ptr->getType())->getElementType();
- APInt Size(PtrBitWidth, DL.getTypeStoreSize(Ty));
-
- // FIXME: Currently the offsets are assumed to be constant.However this not
- // always true as offsets can be variables also and we would need to
- // consider the difference of the variable offsets.
- APInt Offset(PtrBitWidth, 0);
- Ptr->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
- OffValPairs.push_back(std::make_pair(Offset.getSExtValue(), Val));
+
+ // If a pointer refers to a different underlying object, bail - the
+ // pointers are by definition incomparable.
+ Value *CurrObj = GetUnderlyingObject(Ptr, DL);
+ if (CurrObj != Obj0) {
+ Sorted.append(VL.begin(), VL.end());
+ return;
+ }
+
+ const SCEVConstant *Diff =
+ dyn_cast<SCEVConstant>(SE.getMinusSCEV(SE.getSCEV(Ptr), Scev0));
+
+ // The pointers may not have a constant offset from each other, or SCEV
+ // may just not be smart enough to figure out they do. Regardless,
+ // there's nothing we can do.
+ if (!Diff) {
+ Sorted.append(VL.begin(), VL.end());
+ return;
+ }
+
+ OffValPairs.emplace_back(Diff->getAPInt().getSExtValue(), Val);
}
+
std::sort(OffValPairs.begin(), OffValPairs.end(),
- [](const std::pair<int, Value *> &Left,
- const std::pair<int, Value *> &Right) {
+ [](const std::pair<int64_t, Value *> &Left,
+ const std::pair<int64_t, Value *> &Right) {
return Left.first < Right.first;
});
OpenPOWER on IntegriCloud