[Mlir-commits] [mlir] [MLIR] Introduce support for early exits (PR #166688)

Mehdi Amini llvmlistbot at llvm.org
Fri Feb 20 03:03:15 PST 2026


================
@@ -506,33 +506,44 @@ In MLIR, control flow semantics of a region is indicated by
 regions support semantics where operations in a region 'execute sequentially'.
 Before an operation executes, its operands have well-defined values. After an
 operation executes, the operands have the same values and results also have
-well-defined values. After an operation executes, the next operation in the
-block executes until the operation is the terminator operation at the end of a
-block, in which case some other operation will execute. The determination of the
-next instruction to execute is the 'passing of control flow'.
+well-defined values.
+
+Usually, after an operation executes, the next operation in the block executes
+until the operation is the terminator operation at the end of a block, in which
+case the control will be transfered to another block or one of the parent
+operations. The determination of the next instruction to execute is the 'passing
+of control flow'. The control-flow can be interrupted by an operation if it
+defines the `PropagateControlFlowBreak` trait. Such an operation does not
+handle the break itself; it transparently propagates it outward to an ancestor
+operation that implements `HasBreakingControlFlowOpInterface`. The actual break
+is initiated by a nested [Region Terminator](#region-terminator). Every
+operation between the `RegionTerminator` and the receiving
+`HasBreakingControlFlowOpInterface` operation must define
+`PropagateControlFlowBreak`.
 
 In general, when control flow is passed to an operation, MLIR does not restrict
 when control flow enters or exits the regions contained in that operation.
 However, when control flow enters a region, it always begins in the first block
 of the region, called the *entry* block. Terminator operations ending each block
 represent control flow by explicitly specifying the successor blocks of the
 block. Control flow can only pass to one of the specified successor blocks as in
-a `branch` operation, or back to the containing operation as in a `return`
-operation. Terminator operations without successors can only pass control back
-to the containing operation. Within these restrictions, the particular semantics
-of terminator operations is determined by the specific dialect operations
-involved. Blocks (other than the entry block) that are not listed as a successor
-of a terminator operation are defined to be unreachable and can be removed
-without affecting the semantics of the containing operation.
+a `branch` operation, or back to one of the enclosing parent operations, as in a
+`return` operation. Terminator operations without block successors can only pass
----------------
joker-eph wrote:

Good point: looks like we never updated LangRef to allow for `ub.unreachable`.

By the way `ub.unreachable` is a terminator, which means it can't be inserted freely, and it can't be used in ops that check for specific terminators (like scf.if)...

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


More information about the Mlir-commits mailing list