[Mlir-commits] [mlir] [mlir][IR] Add builtin `TokenType` (PR #195640)
Mehdi Amini
llvmlistbot at llvm.org
Wed May 13 01:13:31 PDT 2026
================
@@ -0,0 +1,100 @@
+# Tokens
+
+[TOC]
+
+## Overview
+
+Intuitively, a *token* value is a pointer to an operation (via an OpResult)
+or a pointer to a region (via an entry block argument). A token cannot be
+forwarded: a token def-use chain cannot be obscured by ops with forwarding
+semantics such as `arith.select` or `cf.br`. This allows you to always walk
+back from a use and say "this token came from *that* specific op".
+
+A token is an SSA value that has the builtin token type. The token type is
+parameterless, opaque and carries no runtime data. A token prints as `token`.
+Apart from the structural contract below, tokens are like any other SSA values.
+
+## Design Rationale
+
+The token type allows operations to refer to another operation without a new
+parallel def-use system for operations. It reuses the existing def-use
+machinery for SSA. It introduces no changes to the generic op syntax, the
+bytecode infrastructure or core C++ APIs around `Operation`.
+
+As with regular use-def chains, a token def-use chain is unidirectional. A
+token use points to the token's definition and not the other way around.
+Transformations can remove the use of a token without having to touch or
+inspect the definition of the token.
+
+## Structural Contract
+
+A token use cannot be substituted with another token value: the use of a token
+points directly to a specific producer. Generic transformations must not alter
+or break this link. New uses of a token can be introduced safely. As a
+consequence:
+
+1. A token must not appear as a forwarded value, e.g.:
+ * a forwarded result/operand of a `CallOpInterface` op,
+ * an argument or result type of a `FunctionOpInterface` op (a token
+ block argument *inside* a function body is fine — what is disallowed
+ is forwarding tokens across the call/return boundary),
+ * a successor operand or successor block argument of a
+ `BranchOpInterface` op,
+ * a forwarded operand to/from any region of a `RegionBranchOpInterface`
+ op (iter-args, region results, yielded values), or
+ * the result of any op that selects or merges values it does not
+ understand (e.g. `arith.select`).
----------------
joker-eph wrote:
> I got that, but nothing technically prevents me createing call op that takes token as operand.
You would have to write your own op in C++ or your own ODS constraints, because `AnyType` would catch it.
As I mentioned elsewhere, folks can always creatively find ways to shoot themselves in the foot, our verifiers are pretty defensive but can't be bulletproof either.
> We maybe want to explicitly mention this “soft-correctness” limitation in LangRef?
I don't think so: the rules aren't "softer" because we don't enforce them at some point, the implementation of the verifier and its limitation are to me disconnected from the "specification" that LangRef is meant to encode.
In any case, the traits-solution will catch it.
https://github.com/llvm/llvm-project/pull/195640
More information about the Mlir-commits
mailing list