[Mlir-commits] [mlir] [mlir][tensor]-Handle Dynamic Offset in BubbleUpSliceOpThroughCollapse (PR #178921)

ofri frishman llvmlistbot at llvm.org
Tue Feb 3 23:52:38 PST 2026


================
@@ -602,116 +767,48 @@ LogicalResult mlir::tensor::getExpandedExtractSliceInfo(
     return failure();
   }
 
+  using ReassocGroupResult =
+      std::pair<SmallVector<OpFoldResult>, SmallVector<OpFoldResult>>;
+  SmallVector<ReassocGroupResult> groupResults;
+
   // Compute new offsets, sizes, and strides for tensor.extract_slice.
   // The new tensor.extract_slice will work on a tensor that has has a rank
   // equal to the rank of the src of the collapse_shape. In each iteration of
   // the loop, the offsets and sizes will be computed per reassociation group.
-  expandedStrides.resize(expandedShape.size(), b.getIndexAttr(1));
   for (auto [collapsedSize, collapsedOffset, reassocIndices] :
        llvm::zip_equal(collapsedSizes, collapsedOffsets, reassociation)) {
-    // CASE #1 - size and/or offset are dynamic.
-    // In this case, the slice can be represented as a contiguous slice only
-    // if there is a single dimension in the reassociation group that has a
-    // size not equal to 1.
-    if (isa<Value>(collapsedSize) || isa<Value>(collapsedOffset)) {
-      int nonUnitSizeCount = 0;
-      for (int64_t expandedShapeIdx : reassocIndices) {
-        if (expandedShape[expandedShapeIdx] != 1) {
-          nonUnitSizeCount++;
-          expandedSizes.push_back(collapsedSize);
-          expandedOffsets.push_back(collapsedOffset);
-          continue;
-        }
-
-        expandedSizes.push_back(b.getIndexAttr(1));
-        expandedOffsets.push_back(b.getIndexAttr(0));
-      }
-
-      if (nonUnitSizeCount != 1) {
-        return failure();
-      }
-      continue;
-    }
 
-    // CASE #2 = size and offset are static.
-    // Verify that the slice can be represented as a contiguous slice of the
-    // src of the collapse_shape.
-    // Checking this is done on order of most internal dimensions first,
-    // so traversal is done in reverse order of the reassociation group.
-    // If the expected slice shape is [1, 1, ..., 1, Sk, Ak + 1, Ak + 2,
-    // ...,An] then we first find the size and offset for n...k+1 then for k
-    // and then for k-1...0.
-
-    // currentCollapsedsize and currentCollapsedOffset are initialized with
-    // the original collapsed size and offset and divided by the expanded
-    // shape size in each dimension as we go along the reassociation group.
-    // In essence we are spreading the original collapsed size and offset over
-    // the various expanded slice dimensions.
-    // The variables are used both to check the validity of the slice and to
-    // compute the expanded sizes and offsets.
-    int64_t currentCollapsedsize = getConstantIntValue(collapsedSize).value();
-    int64_t currentCollapsedOffset =
-        getConstantIntValue(collapsedOffset).value();
-    SmallVector<OpFoldResult> groupExpandedSizes, groupExpandedOffsets;
-    ReassociationIndices reversedReassocIndices(reassocIndices.rbegin(),
-                                                reassocIndices.rend());
-    int64_t idx = 0;
-    int64_t reassocGroupSize = reassocIndices.size();
-
-    // First handle the trailing dimensions where the slice size should be
-    // equal to the tensor shape and the offset should be 0 (n...k+1).
-    for (; idx < reassocGroupSize; ++idx) {
-      int64_t expandedShapeSize = expandedShape[reversedReassocIndices[idx]];
-
-      if (currentCollapsedsize < expandedShapeSize)
-        break;
-
-      // We need to make sure that the slice size can be set to the shape size
-      // and the offset to 0.
-      if ((currentCollapsedsize % expandedShapeSize) != 0 ||
-          (currentCollapsedOffset % expandedShapeSize) != 0) {
-        return failure();
-      }
-
-      groupExpandedSizes.push_back(b.getIndexAttr(expandedShapeSize));
-      groupExpandedOffsets.push_back(b.getIndexAttr(0));
+    SmallVector<OpFoldResult> groupSizes;
+    SmallVector<OpFoldResult> groupOffsets;
+    LogicalResult result = computeExpandedSliceInfoForReassocGroup(
+        b, collapsedSize, collapsedOffset, reassocIndices, expandedShape,
+        groupSizes, groupOffsets);
+    if (failed(result))
+      return failure();
+    groupResults.emplace_back(std::make_pair(groupSizes, groupOffsets));
+  }
 
-      currentCollapsedsize /= expandedShapeSize;
-      currentCollapsedOffset /= expandedShapeSize;
-    }
+  expandedStrides.resize(expandedShape.size(), b.getIndexAttr(1));
+  for (auto [groupIdx, reassocIndices] : llvm::enumerate(reassociation)) {
+    auto &[sizes, offsets] = groupResults[groupIdx];
+    expandedSizes.append(sizes);
 
-    // Now handle the first dim where slicing occurs on (k).
-    if (idx < reassocGroupSize) {
-      int64_t expandedShapeSize = expandedShape[reversedReassocIndices[idx]];
-      int64_t offsetInDim = currentCollapsedOffset % expandedShapeSize;
-      // We need to make sure that the slice size in this dim + offset will
-      // not exceed the shape size.
-      if ((currentCollapsedsize + offsetInDim) >= expandedShapeSize) {
-        return failure();
-      }
-      groupExpandedSizes.push_back(b.getIndexAttr(currentCollapsedsize));
-      groupExpandedOffsets.push_back(b.getIndexAttr(offsetInDim));
-      currentCollapsedOffset /= expandedShapeSize;
+    if (!offsets.empty()) {
----------------
ofri-frishman wrote:

it seems counter intuitive that sometimes computeExpandedSliceInfoForReassocGroup returns offsets and sometimes it doesn't. I suggest changing it so it always returns them or always doesn't.

https://github.com/llvm/llvm-project/pull/178921


More information about the Mlir-commits mailing list