[Mlir-commits] [mlir] 05bd2d9 - [mlir] Switch to llvm::cast in generated Op::create() definitions (#217845)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Aug 21 04:12:44 PDT 2026
Author: Andrei Golubev
Date: 2026-08-21T04:12:39-07:00
New Revision: 05bd2d911ecef9c83bcce1fcf05688e403a24312
URL: https://github.com/llvm/llvm-project/commit/05bd2d911ecef9c83bcce1fcf05688e403a24312
DIFF: https://github.com/llvm/llvm-project/commit/05bd2d911ecef9c83bcce1fcf05688e403a24312.diff
LOG: [mlir] Switch to llvm::cast in generated Op::create() definitions (#217845)
Switch from llvm::dyn_cast() to llvm::cast() in the TableGen-generated
code for Op::create() syntax. Repeat the same for the deprecated
OpBuilder::create().
>From the code, it seems the intent was always to unconditionally convert
an abstract operation to a specified operation type. Yet, since
llvm::dyn_cast() is used to perform the conversion, it practically means
that, even in release builds, there's a branch generated for the case if
such conversion fails. This is likely a minuscule problem at a single
operation level but perhaps somewhat affects the overall performance of
the compiler when the number of operations is high (e.g. consider
instruction cache). It looks like what one can do instead is change
llvm::dyn_cast() to llvm::cast() and keep the nice assert-based failure
check via llvm::isa().
Behaviour-wise, in case of failure, dyn_cast would produce a nullptr,
dereferencing which is UB. Now, cast would likely produce a malformed
object which is slightly worse but still technically UB. That is, in
both cases the main expectation is that creation succeeds, and if it
fails, the user is probably going to see the UB.
Disclaimer: no performance measurements were done to back up the claim
of dyn_cast being worse than cast.
Added:
Modified:
mlir/include/mlir/IR/Builders.h
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
mlir/lib/Target/IRDLToCpp/Templates/PerOperationDef.txt
mlir/test/mlir-tblgen/op-decl-and-defs.td
mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/IR/Builders.h b/mlir/include/mlir/IR/Builders.h
index ab5974770da09..0bf41530b14b0 100644
--- a/mlir/include/mlir/IR/Builders.h
+++ b/mlir/include/mlir/IR/Builders.h
@@ -511,9 +511,8 @@ class OpBuilder : public Builder {
getCheckRegisteredInfo<OpTy>(location.getContext()));
OpTy::build(*this, state, std::forward<Args>(args)...);
auto *op = create(state);
- auto result = dyn_cast<OpTy>(op);
- assert(result && "builder didn't return the right type");
- return result;
+ assert((isa<OpTy>(op)) && "builder didn't return the right type");
+ return cast<OpTy>(op);
}
/// Create an operation of specific op type at the current insertion point,
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index 046c7dd0fccff..40d7d3cd91708 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -500,9 +500,9 @@ void {0}::build(::mlir::OpBuilder &opBuilder, ::mlir::OperationState &opState, {
{0} {0}::create(::mlir::OpBuilder &opBuilder, ::mlir::Location location, {1} {2} ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) {{
::mlir::OperationState __state__(location, getOperationName());
build(opBuilder, __state__, {5} {6} attributes);
- auto __res__ = ::llvm::dyn_cast<{0}>(opBuilder.create(__state__));
- assert(__res__ && "builder didn't return the right type");
- return __res__;
+ auto __res__ = opBuilder.create(__state__);
+ assert((::llvm::isa<{0}>(__res__)) && "builder didn't return the right type");
+ return ::llvm::cast<{0}>(__res__);
}
{0} {0}::create(::mlir::ImplicitLocOpBuilder &opBuilder, {1} {2} ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) {{
diff --git a/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDef.txt b/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDef.txt
index f4a1b7a996263..c3fd8ac9db52c 100644
--- a/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDef.txt
+++ b/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDef.txt
@@ -35,9 +35,9 @@ __OP_CPP_NAME__::create(::mlir::OpBuilder &odsBuilder,
{
::mlir::OperationState state(location, getOperationName());
build(odsBuilder, state, resultTypes, operands, attributes);
- auto res = ::llvm::dyn_cast<__OP_CPP_NAME__>(odsBuilder.create(state));
- assert(res && "builder didn't return the right type");
- return res;
+ auto res = odsBuilder.create(state);
+ assert((::llvm::isa<__OP_CPP_NAME__>(res)) && "builder didn't return the right type");
+ return ::llvm::cast<__OP_CPP_NAME__>(res);
}
__OP_CPP_NAME__
diff --git a/mlir/test/mlir-tblgen/op-decl-and-defs.td b/mlir/test/mlir-tblgen/op-decl-and-defs.td
index e92b4044668c1..cd1d471773abc 100644
--- a/mlir/test/mlir-tblgen/op-decl-and-defs.td
+++ b/mlir/test/mlir-tblgen/op-decl-and-defs.td
@@ -236,9 +236,9 @@ def NS_FOp : NS_Op<"op_with_all_types_constraint",
// DEFS: FOp FOp::create(::mlir::OpBuilder &builder, ::mlir::Location location, ::mlir::Value a) {
// DEFS: ::mlir::OperationState __state__(location, getOperationName());
// DEFS: build(builder, __state__, std::forward<decltype(a)>(a));
-// DEFS: auto __res__ = ::llvm::dyn_cast<FOp>(builder.create(__state__));
-// DEFS: assert(__res__ && "builder didn't return the right type");
-// DEFS: return __res__;
+// DEFS: auto __res__ = builder.create(__state__);
+// DEFS: assert((::llvm::isa<FOp>(__res__)) && "builder didn't return the right type");
+// DEFS: return ::llvm::cast<FOp>(__res__);
// DEFS: }
// DEFS: FOp FOp::create(::mlir::ImplicitLocOpBuilder &builder, ::mlir::Value a) {
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index d7c119a31795a..f79ed0ea5ccba 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -234,9 +234,9 @@ static const char *const opCommentHeader = R"(
static const char *const inlineCreateBody = R"(
::mlir::OperationState __state__({0}, getOperationName());
build(builder, __state__{1});
- auto __res__ = ::llvm::dyn_cast<{2}>(builder.create(__state__));
- assert(__res__ && "builder didn't return the right type");
- return __res__;
+ auto __res__ = builder.create(__state__);
+ assert((::llvm::isa<{2}>(__res__)) && "builder didn't return the right type");
+ return ::llvm::cast<{2}>(__res__);
)";
static const char *const inlineCreateBodyImplicitLoc = R"(
More information about the Mlir-commits
mailing list