[Mlir-commits] [mlir] [mlir][IR] Add builtin `TokenType` (PR #195640)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon May 11 07:27:40 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-linalg

Author: Matthias Springer (matthias-springer)

<details>
<summary>Changes</summary>

Introduces a new parameterless, opaque, builtin SSA value type, `!token`. A token cannot appear in a value-forwarding position such as `cf.br`, `arith.select`, `scf.for` iter-args or function call/return. Walking back from any token use reaches the producing operation without crossing such a boundary. Tokens carry no runtime data and cannot
constant-fold.

This contract is enforced by changing the default ODS `AnyType` predicate to exclude tokens. Two complementary predicates are added in `CommonTypeConstraints.td`:
* `Token` accepts only the builtin `TokenType`.
* `AnyTypeOrToken` accepts arbitrary types including tokens.

Note: CSE, DCE, hoisting, and `OperationEquivalence` remain unchanged. A stronger contract (e.g., uniqueness, arity, paired lifetime), if desirable based on the semantics of token-producing and token-consuming ops, can be expressed at the op level via existing mechanisms (side effects, block arguments, traits, attributes), keeping the type orthogonal to operation-level transformations. This mirrors LLVM's `token` type.

Other changes:
* Builtin bytecode: new entry for `TokenType`.
* AsmParser / AsmPrinter: `token` keyword for the textual format.
* LLVM dialect: the nested type parser now tries LLVM short-hand keywords (`token`, `void`, `ptr`, ...) before falling back to a generic MLIR type, so `!llvm.token` continues to resolve to `LLVMTokenType` even though `token` is now also a builtin keyword.
* Async dialect: references to `async::TokenType` are qualified to disambiguate from the new builtin `TokenType`.
* Documentation: new `mlir/docs/Tokens.md` covering the structural contract, design rationale, and ODS integration.

No changes to `Operation`, the generic op syntax, the bytecode op encoding, or core C++ APIs around `Operation`.

This commit is in preparation of adding support for breaking exit from regions. (E.g., early exit from loops.)

RFC: https://discourse.llvm.org/t/rfc-add-a-builtin-token-type-to-mlir/90706

Assisted-by: claude-opus-4.7-thinking-high


---

Patch is 53.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/195640.diff


30 Files Affected:

- (added) mlir/docs/Tokens.md (+104) 
- (modified) mlir/include/mlir/Dialect/Async/IR/Async.h (+1-1) 
- (modified) mlir/include/mlir/Dialect/Async/IR/AsyncOps.td (+3-1) 
- (modified) mlir/include/mlir/IR/BuiltinDialectBytecode.td (+4-1) 
- (modified) mlir/include/mlir/IR/BuiltinTypes.td (+20) 
- (modified) mlir/include/mlir/IR/CommonTypeConstraints.td (+18-2) 
- (modified) mlir/lib/AsmParser/TokenKinds.def (+1) 
- (modified) mlir/lib/AsmParser/TypeParser.cpp (+6) 
- (modified) mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp (+18-17) 
- (modified) mlir/lib/Dialect/Async/IR/Async.cpp (+5-5) 
- (modified) mlir/lib/Dialect/Async/Transforms/AsyncRuntimeRefCounting.cpp (+1-1) 
- (modified) mlir/lib/Dialect/Async/Transforms/AsyncToAsyncRuntime.cpp (+8-6) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMTypeSyntax.cpp (+36-24) 
- (modified) mlir/lib/IR/AsmPrinter.cpp (+1) 
- (modified) mlir/test/Dialect/ArmSME/invalid.mlir (+2-2) 
- (modified) mlir/test/Dialect/Builtin/Bytecode/builtin_fixed.mlir (+3-1) 
- (modified) mlir/test/Dialect/Builtin/Bytecode/builtin_fixed_0.mlirbc () 
- (modified) mlir/test/Dialect/Builtin/Bytecode/types.mlir (+10) 
- (modified) mlir/test/Dialect/Linalg/invalid.mlir (+2-2) 
- (modified) mlir/test/Dialect/MemRef/invalid.mlir (+2-2) 
- (modified) mlir/test/Dialect/SparseTensor/invalid.mlir (+12-12) 
- (modified) mlir/test/Dialect/Tensor/invalid.mlir (+1-1) 
- (modified) mlir/test/Dialect/Vector/invalid.mlir (+5-5) 
- (modified) mlir/test/Dialect/traits.mlir (+1-1) 
- (modified) mlir/test/IR/operand.mlir (+3-3) 
- (modified) mlir/test/IR/result.mlir (+3-3) 
- (added) mlir/test/IR/token-type.mlir (+60) 
- (modified) mlir/test/lib/Dialect/Test/TestOps.td (+30) 
- (modified) mlir/test/mlir-tblgen/predicate.td (+2-2) 
- (modified) mlir/test/mlir-tblgen/types.mlir (+3-3) 


``````````diff
diff --git a/mlir/docs/Tokens.md b/mlir/docs/Tokens.md
new file mode 100644
index 0000000000000..51d4005f4723c
--- /dev/null
+++ b/mlir/docs/Tokens.md
@@ -0,0 +1,104 @@
+# 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 prints as `token`. A token carries no runtime data.
+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. The existing def-use machinery for SSA
+values can be reused. Moreover, no changes were needed for the generic op
+syntax, the bytecode infrastructure and 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. (But not the other way around.)
+Transformations can remove the use of a token without having to touch or
+inspect the definition of the token. (Whether such a transformation is correct
+depends on the semantics of the token-producing and token-consuming ops.)
+
+Token-producing and token-consuming ops are subject to standard transformations
+such as CSE, DCE and hoisting. If such transformations are not desirable due to
+op semantics, common IR design patterns can be employed. To give a few examples:
+Terminators or ops with side effects are not CSE'd or DCE'd. Region block
+arguments semantically belong to the enclosing op and are never CSE'd, DCE'd or
+hoisted. Non-speculatability may also prevent hoisting.
+
+## Structural Contract
+
+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`).
+
+2. As a consequence of (1), given a use of a token SSA value, its definition is
+   guaranteed to be the semantic producer of the token.
+
+3. A token cannot constant-fold. No constant of token type exists.
+
+These properties mirror what LLVM IR already documents for its own
+[`token` type](https://llvm.org/docs/LangRef.html#token-type).
+
+## ODS Integration
+
+Tokens are excluded from the default `AnyType` predicate, so an op that has
+not opted in cannot accept a token as an arbitrary operand or result. This
+restriction prevents tokens from being accidentally passed as operands with
+forwarding semantics.
+
+Three predicates are provided in `CommonTypeConstraints.td`:
+
+| Predicate          | Accepts                              | Use when …                                                            |
+| ------------------ | ------------------------------------ | ----------------------------------------------------------------------|
+| `AnyType`          | any non-token type                   | the default; matches the historical meaning of "any type" pre-tokens. |
+| `AnyTypeOrToken`   | any type, including tokens           | the op legitimately accepts arbitrary types (including tokens).       |
+| `Token`            | only the builtin `TokenType`         | the op specifically takes a token operand/result.                     |
+
+Example:
+
+```tablegen
+def MyConsumeOp : MyDialect_Op<"consume"> {
+  let arguments = (ins Token:$scope, AnyType:$value);
+}
+```
+
+## Examples
+
+### Rejected: tokens in `AnyType` positions
+
+`scf.yield` operands have forwarding semantics. A token cannot be yielded from
+a branch or a loop.
+
+```mlir
+// error: 'scf.if' op result #0 must be variadic of any non-token type,
+//        but got 'token'
+%t = scf.if %cond -> token {
+  %a = my.token.produce : token
+  scf.yield %a : token
+} else {
+  %b = my.token.produce : token
+  scf.yield %b : token
+}
+```
+
+`scf.if`'s results are declared with `Variadic<AnyType>` and `scf.yield`'s
+operands likewise use `AnyType`. Because `AnyType` excludes tokens by
+default, yielding (or returning) a token through a `scf.if` (or any other
+op that has not explicitly opted in via `AnyTypeOrToken`) is rejected.
diff --git a/mlir/include/mlir/Dialect/Async/IR/Async.h b/mlir/include/mlir/Dialect/Async/IR/Async.h
index f16e87e71373a..fc0b086126f52 100644
--- a/mlir/include/mlir/Dialect/Async/IR/Async.h
+++ b/mlir/include/mlir/Dialect/Async/IR/Async.h
@@ -50,7 +50,7 @@ namespace async {
 
 /// Returns true if the type is reference counted at runtime.
 inline bool isRefCounted(Type type) {
-  return isa<TokenType, ValueType, GroupType>(type);
+  return isa<async::TokenType, ValueType, GroupType>(type);
 }
 
 } // namespace async
diff --git a/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td b/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
index 2cebeac767f29..058f58bda6433 100644
--- a/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
+++ b/mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
@@ -174,7 +174,9 @@ def Async_FuncOp : Async_Op<"func",
     unsigned getNumResults() {return getResultTypes().size();}
 
     /// Is the async func stateful
-    bool isStateful() { return isa<TokenType>(getFunctionType().getResult(0));}
+    bool isStateful() {
+      return isa<async::TokenType>(getFunctionType().getResult(0));
+    }
 
     //===------------------------------------------------------------------===//
     // OpAsmOpInterface Methods
diff --git a/mlir/include/mlir/IR/BuiltinDialectBytecode.td b/mlir/include/mlir/IR/BuiltinDialectBytecode.td
index c97d093c84e51..99bcf70c77564 100644
--- a/mlir/include/mlir/IR/BuiltinDialectBytecode.td
+++ b/mlir/include/mlir/IR/BuiltinDialectBytecode.td
@@ -294,6 +294,8 @@ def UnrankedTensorType : DialectType<(type
   Type:$elementType
 )>;
 
+def TokenType : DialectType<(type)>;
+
 let cType = "VectorType" in {
 def VectorType : DialectType<(type
   Array<SignedVarIntList>:$shape,
@@ -371,7 +373,8 @@ def BuiltinDialectTypes : DialectTypes<"Builtin"> {
     UnrankedMemRefTypeWithMemSpace,
     UnrankedTensorType,
     VectorType,
-    VectorTypeWithScalableDims
+    VectorTypeWithScalableDims,
+    TokenType
   ];
 }
 
diff --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td
index 20c41c5f79729..3d36ffa5802c3 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -1237,6 +1237,26 @@ def Builtin_RankedTensor : Builtin_Type<"RankedTensor", "tensor", [
   let genVerifyDecl = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// TokenType
+//===----------------------------------------------------------------------===//
+
+def Builtin_Token : Builtin_Type<"Token", "token"> {
+  let summary = "Token type";
+  let description = [{
+    Syntax:
+
+    ```
+    token-type ::= `token`
+    ```
+
+    A use of a token SSA value is a pointer to an operation (in case of an
+    OpResult) or a pointer to a region (in case of an entry block argument).
+    A token carries no runtime data and cannot be forwarded. Tokens are
+    excluded from the `AnyType` type constraint.
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // TupleType
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/IR/CommonTypeConstraints.td b/mlir/include/mlir/IR/CommonTypeConstraints.td
index 57caaae08462f..86066bcda73e6 100644
--- a/mlir/include/mlir/IR/CommonTypeConstraints.td
+++ b/mlir/include/mlir/IR/CommonTypeConstraints.td
@@ -165,8 +165,24 @@ class SameBuildabilityAs<Type type, code builder> {
   code builderCall = !if(!empty(type.builderCall), "", builder);
 }
 
-// Any type at all.
-def AnyType : Type<CPred<"true">, "any type">;
+// Whether a type is the builtin `TokenType`.
+def IsTokenTypePred : CPred<"::llvm::isa<::mlir::TokenType>($_self)">;
+
+// Any non-token type. Tokens are excluded by default to prevent ops that
+// accept arbitrary types from accidentally accepting tokens as operands /
+// results, since a token must not be value-forwarded. Ops that legitimately
+// want to accept any type, including tokens, should use `AnyTypeOrToken`
+// instead.
+def AnyType : Type<Neg<IsTokenTypePred>, "any non-token type">;
+
+// Any type at all, including tokens. Used by ops that explicitly opt in to
+// accepting tokens (e.g. ops in interfaces such as `CallOpInterface`,
+// `BranchOpInterface`, etc. that legitimately handle arbitrary types).
+def AnyTypeOrToken : Type<CPred<"true">, "any type">;
+
+// The builtin token type.
+def Token : Type<IsTokenTypePred, "token", "::mlir::TokenType">,
+            BuildableType<"$_builder.getType<::mlir::TokenType>()">;
 
 // None type
 def NoneType : Type<CPred<"::llvm::isa<::mlir::NoneType>($_self)">, "none type",
diff --git a/mlir/lib/AsmParser/TokenKinds.def b/mlir/lib/AsmParser/TokenKinds.def
index fe7c53753e156..f5e5c25832a30 100644
--- a/mlir/lib/AsmParser/TokenKinds.def
+++ b/mlir/lib/AsmParser/TokenKinds.def
@@ -127,6 +127,7 @@ TOK_KEYWORD(symbol)
 TOK_KEYWORD(tensor)
 TOK_KEYWORD(tf32)
 TOK_KEYWORD(to)
+TOK_KEYWORD(token)
 TOK_KEYWORD(true)
 TOK_KEYWORD(tuple)
 TOK_KEYWORD(type)
diff --git a/mlir/lib/AsmParser/TypeParser.cpp b/mlir/lib/AsmParser/TypeParser.cpp
index a461ebed967a8..2cdec14d65fa6 100644
--- a/mlir/lib/AsmParser/TypeParser.cpp
+++ b/mlir/lib/AsmParser/TypeParser.cpp
@@ -58,6 +58,7 @@ OptionalParseResult Parser::parseOptionalType(Type &type) {
   case Token::kw_f128:
   case Token::kw_index:
   case Token::kw_none:
+  case Token::kw_token:
   case Token::exclamation_identifier:
     return failure(!(type = parseType()));
 
@@ -371,6 +372,11 @@ Type Parser::parseNonFunctionType() {
     consumeToken(Token::kw_none);
     return builder.getNoneType();
 
+  // token-type
+  case Token::kw_token:
+    consumeToken(Token::kw_token);
+    return builder.getType<TokenType>();
+
   // extended type
   case Token::exclamation_identifier:
     return parseExtendedType();
diff --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
index 29e6552231f9c..7844c9dda877c 100644
--- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
+++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
@@ -89,7 +89,7 @@ struct AsyncAPI {
   }
 
   static FunctionType createTokenFunctionType(MLIRContext *ctx) {
-    return FunctionType::get(ctx, {}, {TokenType::get(ctx)});
+    return FunctionType::get(ctx, {}, {async::TokenType::get(ctx)});
   }
 
   static FunctionType createValueFunctionType(MLIRContext *ctx) {
@@ -109,7 +109,7 @@ struct AsyncAPI {
   }
 
   static FunctionType emplaceTokenFunctionType(MLIRContext *ctx) {
-    return FunctionType::get(ctx, {TokenType::get(ctx)}, {});
+    return FunctionType::get(ctx, {async::TokenType::get(ctx)}, {});
   }
 
   static FunctionType emplaceValueFunctionType(MLIRContext *ctx) {
@@ -118,7 +118,7 @@ struct AsyncAPI {
   }
 
   static FunctionType setTokenErrorFunctionType(MLIRContext *ctx) {
-    return FunctionType::get(ctx, {TokenType::get(ctx)}, {});
+    return FunctionType::get(ctx, {async::TokenType::get(ctx)}, {});
   }
 
   static FunctionType setValueErrorFunctionType(MLIRContext *ctx) {
@@ -128,7 +128,7 @@ struct AsyncAPI {
 
   static FunctionType isTokenErrorFunctionType(MLIRContext *ctx) {
     auto i1 = IntegerType::get(ctx, 1);
-    return FunctionType::get(ctx, {TokenType::get(ctx)}, {i1});
+    return FunctionType::get(ctx, {async::TokenType::get(ctx)}, {i1});
   }
 
   static FunctionType isValueErrorFunctionType(MLIRContext *ctx) {
@@ -143,7 +143,7 @@ struct AsyncAPI {
   }
 
   static FunctionType awaitTokenFunctionType(MLIRContext *ctx) {
-    return FunctionType::get(ctx, {TokenType::get(ctx)}, {});
+    return FunctionType::get(ctx, {async::TokenType::get(ctx)}, {});
   }
 
   static FunctionType awaitValueFunctionType(MLIRContext *ctx) {
@@ -162,13 +162,14 @@ struct AsyncAPI {
 
   static FunctionType addTokenToGroupFunctionType(MLIRContext *ctx) {
     auto i64 = IntegerType::get(ctx, 64);
-    return FunctionType::get(ctx, {TokenType::get(ctx), GroupType::get(ctx)},
-                             {i64});
+    return FunctionType::get(
+        ctx, {async::TokenType::get(ctx), GroupType::get(ctx)}, {i64});
   }
 
   static FunctionType awaitTokenAndExecuteFunctionType(MLIRContext *ctx) {
     auto ptrType = opaquePointerType(ctx);
-    return FunctionType::get(ctx, {TokenType::get(ctx), ptrType, ptrType}, {});
+    return FunctionType::get(
+        ctx, {async::TokenType::get(ctx), ptrType, ptrType}, {});
   }
 
   static FunctionType awaitValueAndExecuteFunctionType(MLIRContext *ctx) {
@@ -291,7 +292,7 @@ class AsyncRuntimeTypeConverter : public TypeConverter {
   }
 
   static std::optional<Type> convertAsyncTypes(Type type) {
-    if (isa<TokenType, GroupType, ValueType>(type))
+    if (isa<async::TokenType, GroupType, ValueType>(type))
       return AsyncAPI::opaquePointerType(type.getContext());
 
     if (isa<CoroIdType, CoroStateType>(type))
@@ -583,7 +584,7 @@ class RuntimeCreateOpLowering : public ConvertOpToLLVMPattern<RuntimeCreateOp> {
     Type resultType = op->getResultTypes()[0];
 
     // Tokens creation maps to a simple function call.
-    if (isa<TokenType>(resultType)) {
+    if (isa<async::TokenType>(resultType)) {
       rewriter.replaceOpWithNewOp<func::CallOp>(
           op, kCreateToken, converter->convertType(resultType));
       return success();
@@ -659,7 +660,7 @@ class RuntimeSetAvailableOpLowering
                   ConversionPatternRewriter &rewriter) const override {
     StringRef apiFuncName =
         TypeSwitch<Type, StringRef>(op.getOperand().getType())
-            .Case<TokenType>([](Type) { return kEmplaceToken; })
+            .Case<async::TokenType>([](Type) { return kEmplaceToken; })
             .Case<ValueType>([](Type) { return kEmplaceValue; });
 
     rewriter.replaceOpWithNewOp<func::CallOp>(op, apiFuncName, TypeRange(),
@@ -685,7 +686,7 @@ class RuntimeSetErrorOpLowering
                   ConversionPatternRewriter &rewriter) const override {
     StringRef apiFuncName =
         TypeSwitch<Type, StringRef>(op.getOperand().getType())
-            .Case<TokenType>([](Type) { return kSetTokenError; })
+            .Case<async::TokenType>([](Type) { return kSetTokenError; })
             .Case<ValueType>([](Type) { return kSetValueError; });
 
     rewriter.replaceOpWithNewOp<func::CallOp>(op, apiFuncName, TypeRange(),
@@ -710,7 +711,7 @@ class RuntimeIsErrorOpLowering : public OpConversionPattern<RuntimeIsErrorOp> {
                   ConversionPatternRewriter &rewriter) const override {
     StringRef apiFuncName =
         TypeSwitch<Type, StringRef>(op.getOperand().getType())
-            .Case<TokenType>([](Type) { return kIsTokenError; })
+            .Case<async::TokenType>([](Type) { return kIsTokenError; })
             .Case<GroupType>([](Type) { return kIsGroupError; })
             .Case<ValueType>([](Type) { return kIsValueError; });
 
@@ -735,7 +736,7 @@ class RuntimeAwaitOpLowering : public OpConversionPattern<RuntimeAwaitOp> {
                   ConversionPatternRewriter &rewriter) const override {
     StringRef apiFuncName =
         TypeSwitch<Type, StringRef>(op.getOperand().getType())
-            .Case<TokenType>([](Type) { return kAwaitToken; })
+            .Case<async::TokenType>([](Type) { return kAwaitToken; })
             .Case<ValueType>([](Type) { return kAwaitValue; })
             .Case<GroupType>([](Type) { return kAwaitGroup; });
 
@@ -763,7 +764,7 @@ class RuntimeAwaitAndResumeOpLowering
                   ConversionPatternRewriter &rewriter) const override {
     StringRef apiFuncName =
         TypeSwitch<Type, StringRef>(op.getOperand().getType())
-            .Case<TokenType>([](Type) { return kAwaitTokenAndExecute; })
+            .Case<async::TokenType>([](Type) { return kAwaitTokenAndExecute; })
             .Case<ValueType>([](Type) { return kAwaitValueAndExecute; })
             .Case<GroupType>([](Type) { return kAwaitAllAndExecute; });
 
@@ -906,7 +907,7 @@ class RuntimeAddToGroupOpLowering
   matchAndRewrite(RuntimeAddToGroupOp op, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
     // Currently we can only add tokens to the group.
-    if (!isa<TokenType>(op.getOperand().getType()))
+    if (!isa<async::TokenType>(op.getOperand().getType()))
       return rewriter.notifyMatchFailure(op, "only token type is supported");
 
     // Replace with a runtime API function call.
@@ -1151,7 +1152,7 @@ class ConvertYieldOpTypes : public OpConversionPattern<async::YieldOp> {
 void mlir::populateAsyncStructuralTypeConversionsAndLegality(
     TypeConverter &typeConverter, RewritePatternSet &patterns,
     ConversionTarget &target) {
-  typeConverter.addConversion([&](TokenType type) { return type; });
+  typeConverter.addConversion([&](async::TokenType type) { return type; });
   typeConverter.addConversion([&](ValueType type) {
     Type converted = typeConverter.convertType(type.getValueType());
     return converted ? ValueType::get(converted) : converted;
diff --git a/mlir/lib/Dialect/Async/IR/Async.cpp b/mlir/lib/Dialect/Async/IR/Async.cpp
index 71be1d275280e..1713da07da60d 100644
--- a/mlir/lib/Dialect/Async/IR/Async.cpp
+++ b/mlir/lib/Dialect/Async/IR/Async.cpp
@@ -84,7 +84,7 @@ void ExecuteOp::build(OpBuilder &builder, OperationState &result,
 
   // First result is always a token, and then `resultTypes` wrapped into
   // `async.value`.
-  result.addTypes({TokenType::get(result.getContext())});
+  result.addTypes({async::TokenType::get(result.getContext())});
   for (Type type : resultTypes)
     result.addTypes(ValueType::get(type));
 
@@ -139,7 +139,7 @@ ParseResult ExecuteOp::parse(OpAsmParser &parser, OperationState &result) {
   // Sizes of parsed variadic operands, will be updated below after parsing.
   int32_t numDependencies = 0;
 
-  auto tokenTy = TokenType::get(ctx);
+  auto tokenTy = async::TokenType::get(ctx);
 
   // Parse dependency tokens.
   if (succeeded(parser.parseOptionalLSquare())) {
@@ -280,7 +280,7 @@ LogicalResult AwaitOp::verify() {
   Type argType = getOperand().getType();
 
   // Awaiting on a token does not have any results.
-  if (llvm::isa<TokenType>(argType) && !getResultTypes().empty())
+  if (llvm::isa<async::TokenType>(argType) && !getResultTypes().empty())
     return emitOpError("awaiting on a token must have empty result");
 
   // Awaiting on a value unwraps the async value type.
@@ -345,12 +345,12 @@ LogicalResult FuncOp::verify() {
 
   for (unsigned i = 0, e = resultTypes.size(); i != e; ++i) {
     auto type = resultTypes[i];
-    if (!llvm::isa<TokenType>(type) && !llvm::isa<ValueType>(type))
+    if (!llvm::isa<async::TokenType>(type) && !llvm::isa<ValueType>(type))
       return emitOpError() << "result type must be async value type or async "
                               "token type, but got "
                            << type;
     // We only allow AsyncToken appear as the first return value
-    if (llvm::isa<TokenType>(type) && i != 0) {
+    if (llvm::isa<async::TokenType>(type) && i != 0) {
       return emitOpError()
              << " results' (optional) async token type is expected "
                 "to appear as the 1st return value, but got "
diff --git a/mlir/lib/Dialect/Async/Transforms/AsyncRuntimeRefCounting.cpp b/mlir/lib/Dialect/Async/Transforms/AsyncRuntimeRefCounting.cpp
index 91e37dd9ac36e..2a726f3fd2999 100644
--- a/mlir/lib/Dialect/Async/Transforms/AsyncRuntimeRefCounting.cpp
+++ b/mlir/lib/Dialect/Async/Transforms/AsyncRuntimeRefCounting.cpp
@@ -526,7 +526,7 @@ void AsyncRuntimePolicyBasedRefCountingPass::i...
[truncated]

``````````

</details>


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


More information about the Mlir-commits mailing list