================
@@ -4923,7 +4969,49 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
assert(Offsets.Splits.empty() &&
"Should not have splits the first time we see an instruction!");
Offsets.S = &S;
- Offsets.Splits.push_back(P.endOffset() - S.beginOffset());
+ if (CopyOverlap) {
+ // S is being moved to CopyOverlap, which overlaps with S, so we split S
+ // into three parts:
+ // * Initially outside the overlap and copied into the overlap.
+ // * Either initially inside the overlap and remains inside it after
+ // the copy, or initially outside and remains outside, depending on
+ // if the overlap or non-overlap area is larger, and which will be
+ // empty if they are equal.
+ // * Initially inside the overlap and copied outside the overlap.
+ // This should result in the first and last parts being promoted to
+ // scalars. If the middle part is an overlapping copy then we repeat
+ // this process until it isn't.
+ uint64_t OverlapStart =
+ std::max(S.beginOffset(), CopyOverlap->beginOffset());
+ uint64_t OverlapEnd = std::min(S.endOffset(), CopyOverlap->endOffset());
+ uint64_t OverlapSize = OverlapEnd - OverlapStart;
+ uint64_t SliceSize = S.endOffset() - S.beginOffset();
+ uint64_t NonOverlapSize = SliceSize - OverlapSize;
+ if (OverlapSize < NonOverlapSize) {
+ // When the overlap area is smaller the middle part is initially
+ // and remains outside the overlap, so splitting once is enough.
+ Offsets.Splits.push_back(OverlapSize);
----------------
john-brawn-arm wrote:
If the current slice has lower start offset then we have something that looks like this:
```
XXXYYZZZ
AAABBCCC
```
X is copied to A, Y is copied to B, and Z is copied to C, so we need split points between X and Y, and between Y and Z. The size of X is the size of the overlapping area, so the split point between X and Y is at OverlapSize. The size of Z is also the size of the overlapping area, so the split point between Y and Z is SliceSize-OverlapSize, but given that SliceSize is OverlapSize+NonOverlapSize this is OverlapSize+NonOverlapSize-OverlapSize, or just NonOverlapSize.
If the current slice has higher start offset then we have
```
XXXYYZZZ
AAABBCCC
```
The above logic for where to put the split points is the same, the only difference is that in the above X is outsize the overlap and copied into the overlap, now it's inside the overlap and copied outside the overlap, but this doesn't change where to put the split points.
https://github.com/llvm/llvm-project/pull/210061