[llvm] [SROA] Pre-split overlapping move slices within a partition (PR #210061)

John Brawn via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 04:07:16 PDT 2026


================
@@ -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


More information about the llvm-commits mailing list