[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