[Mlir-commits] [mlir] [mlir][Vector] Reject invalid inline yields (PR #206218)

Alessandro Potenza llvmlistbot at llvm.org
Sat Aug 29 23:59:15 PDT 2026


https://github.com/alepot55 commented:

I built `11e915f2b75d` and ran the repro from #206083 plus three variants of it, changing only the terminator:

```mlir
llvm.func @callee(%arg0: vector<8xf32>) {
  %0 = math.atanh %arg0 : vector<8xf32>
  vector.yield %arg0 : vector<8xf32>     // <- gpu.yield / linalg.yield / affine.yield
}
llvm.func @caller(%arg0: vector<8xf32>) attributes {llvm.emit_c_interface} {
  llvm.call @callee(%arg0) : (vector<8xf32>) -> ()
  llvm.return
}
```

`mlir-opt -inline`, verbatim:

| terminator | result |
| --- | --- |
| `vector.yield` | `must implement handleTerminator in the case of one inlined block`, UNREACHABLE |
| `gpu.yield` | the same UNREACHABLE |
| `linalg.yield` | `'linalg.yield' op expected parent op with LinalgOp interface` |
| `affine.yield` | `'affine.yield' op only terminates affine.if/for/parallel regions` |

Two things follow.

**Vector is not alone.** `GPUInlinerInterface` in `GPUDialect.cpp` is the same code this PR is changing, down to the comment:

```cpp
/// All gpu dialect ops can be inlined.
bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
  return true;
}
```

GPU has no `handleTerminator` either, and `gpu.yield` has exactly one parent in the tree, `gpu.warp_execute_on_lane_0`. Whatever shape this lands in, GPU needs the same change; I am happy to send that patch once the shape here is settled.

**The tree has already answered this twice, and not in an inliner interface.** Scanning `mlir/include/mlir/Dialect` for ops that declare both `ReturnLike` and `Terminator` and no `HasParent`/`ParentOneOf` turns up six: `spirv.Return`, `spirv.ReturnValue`, `gpu.yield`, `linalg.yield`, `vector.yield`, `affine.yield`. The two in that list that decline the input above do it in their own verifier, not in the inliner: `AffineYieldOp::verify()` rejects any parent outside `affine.if/for/parallel`, and `linalg.yield` requires a parent implementing `LinalgOp`.

That is worth weighing here, because a verifier makes the IR invalid for every consumer, whereas this patch teaches one pass to decline and leaves the same IR to be built by anything else. `vector.yield`'s own definition says the semantics "is defined by the parent operation", and `vector.mask` is the only op in tree using it as a terminator, so the constraint exists to be written down.

The argument the other way is real too: a verifier breaks out-of-tree ops that use `vector.yield` as their terminator, and this patch does not. That trade is for @banach-space and @dcaballe to call, not me. But it should be called deliberately, since the answer also decides what happens to `gpu.yield`.

Separately, and only because it will hold this up regardless of the technical outcome: @PragmaTwice's question from 24 July about the AI Tool Use Policy is still unanswered on this PR.

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


More information about the Mlir-commits mailing list