[Mlir-commits] [mlir] [MLIR][Transform] Fix crash in transform.structured.split with zero-result operations (PR #204363)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Jun 17 08:00:09 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: JasonHonKL

<details>
<summary>Changes</summary>

### Problem:
transform.structured.split crashes when the dynamic chunk size handle points to an operation with no results (e.g., a void function call).

### Root Cause:
In SplitOp::apply(), the code unconditionally accesses op->getResult(0) after detecting an error condition, causing an assertion failure when the operation has 0 results:

```c++
if (op->getNumResults() != 1 || !op->getResult(0).getType().isIndex()) {
  diag = emitSilenceableError()...  // Sets error
}
return OpFoldResult(op->getResult(0));  // Always executes → CRASH
```

Solution:

Split the validation into two separate checks with early returns to prevent accessing invalid result indices:

1. First check if operation has exactly 1 result
2. If not, return empty OpFoldResult()
3. Then safely check if result type is index
4. If not, return empty OpFoldResult()
5. Only access getResult(0) when safe


Testing:
Before fix:

```
Aborted (core dumped)
Assertion `resultNumber < getNumResults()' failed
```

After fix:

```
error: expected dynamic split point handle to point to a single-result index-typed op
  --> test.mlir:7:12
   |
 7 |   %2 = transform.structured.split %0 after %1  {dimension = 0 : i64}
   |                                   ^^
note: dynamic split point
  --> test.mlir:16:5
    |
 16 |   call @<!-- -->m0() : () -> ()
    |   ^
```
Changes:

- Modified mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
- Split error validation into two separate checks
- Added early returns to prevent invalid result access
- Now provides clear error message instead of crashing


Fix issue #<!-- -->204291

---
Full diff: https://github.com/llvm/llvm-project/pull/204363.diff


1 Files Affected:

- (modified) mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp (+12-3) 


``````````diff
diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
index f44693096b26b..aa55d39e1af23 100644
--- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
+++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
@@ -2882,13 +2882,22 @@ SplitOp::apply(transform::TransformRewriter &rewriter,
     if (isa<TransformHandleTypeInterface>(getDynamicChunkSizes().getType())) {
       chunkSizes = llvm::map_to_vector(
           state.getPayloadOps(getDynamicChunkSizes()), [&](Operation *op) {
-            if (op->getNumResults() != 1 ||
-                !op->getResult(0).getType().isIndex()) {
+            if (op -> getNumResults() != 1){
               diag = emitSilenceableError()
-                     << "expected dynamic split point handle to point to a "
+                    << "expected dynamic split point handle to point to a "
                         "single-result index-typed op";
               diag.attachNote(op->getLoc()) << "dynamic split point";
+              return OpFoldResult();  
             }
+
+            if (!op->getResult(0).getType().isIndex()){
+              diag = emitSilenceableError()
+                    << "expected dynamic split point handle to point to a "
+                        "single-result index-typed op";
+              diag.attachNote(op->getLoc()) << "dynamic split point";
+              return OpFoldResult(); 
+            }
+
             return OpFoldResult(op->getResult(0));
           });
     } else {

``````````

</details>


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


More information about the Mlir-commits mailing list