[Mlir-commits] [mlir] [mlir][LangRef] Clarify terminator continuations (PR #201111)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Jun 2 06:05:52 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Mehdi Amini (joker-eph)

<details>
<summary>Changes</summary>

Document that terminators may have no normal control-flow continuation, such as ub.unreachable. Also clarify that no-return calls do not remove the structural terminator requirement.

Assisted-by: Codex

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


1 Files Affected:

- (modified) mlir/docs/LangRef.md (+24-17) 


``````````diff
diff --git a/mlir/docs/LangRef.md b/mlir/docs/LangRef.md
index 0e6fb006da48b..fe5a41b4e4790 100644
--- a/mlir/docs/LangRef.md
+++ b/mlir/docs/LangRef.md
@@ -370,8 +370,10 @@ block-arg-list ::= `(` value-id-and-type-list? `)`
 A *Block* is a list of operations. In
 [SSACFG regions](#control-flow-and-ssacfg-regions), each block represents a
 compiler [basic block](https://en.wikipedia.org/wiki/Basic_block) where
-instructions inside the block are executed in order and terminator operations
-implement control flow branches between basic blocks.
+instructions inside the block are executed in order. Terminator operations mark
+the end of a block and describe the block's possible normal continuations, such
+as branches to other blocks in the same region, returns/yields to the containing
+operation, or no normal continuation at all (e.g. `ub.unreachable`).
 
 The last operation in a block must be a
 [terminator operation](#control-flow-and-ssacfg-regions). A region with a single
@@ -503,25 +505,27 @@ In MLIR, control flow semantics of a region is indicated by
 [RegionKind::SSACFG](Interfaces.md/#regionkindinterfaces). Informally, these
 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'.
+operation executes and has a normal continuation, the operands have the same
+values and results also have well-defined values. The next operation in the
+block then executes until the operation is the terminator operation at the end
+of a block, in which case the terminator determines the next normal
+continuation, if any. The determination of the next instruction to execute is
+the 'passing of control flow'.
 
 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.
+represent possible normal continuations. Successor operands explicitly specify
+destination blocks, so normal control flow within the region can only pass to
+one of the specified successor blocks, as in a `branch` operation. A terminator
+may instead pass control back to the containing operation, as in a `return`
+operation, or define that normal control flow does not continue at all, as in
+`ub.unreachable`. Terminators without successors therefore do not imply a return
+to the containing operation; the specific dialect operation determines the
+terminator's semantics. 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.
 
 Although control flow always enters a region through the entry block, control
 flow may exit a region through any block with an appropriate terminator. The
@@ -530,7 +534,10 @@ Single-Entry-Multiple-Exit (SEME) regions, possibly flowing through different
 blocks in the region and exiting through any block with a `return` operation.
 This behavior is similar to that of a function body in most programming
 languages. In addition, control flow may also not reach the end of a block or
-region, for example if a function call does not return.
+region, for example if a function call does not return. Such an operation
+prevents control flow from reaching later operations on that dynamic path, but
+does not remove the structural requirement that the block end with a terminator
+unless the enclosing operation opts out with `NoTerminator`.
 
 Example:
 

``````````

</details>


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


More information about the Mlir-commits mailing list