[Mlir-commits] [mlir] [mlir] Reduce template work in operation registration (NFC) (PR #233051)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Oct 17 01:19:07 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-core
Author: Mehdi Amini (joker-eph)
<details>
<summary>Changes</summary>
Save use 3.18% less user CPU when building LLVM/NVVM/ROCDL, and 0.96% total user CPU when building mlir-opt. Linked mlir-opt code is 0.60% smaller.
The main thing is to share no-op helper specializations among traits that do not define fold, verification, region-verification, or interface hooks. We also preserve pack order and short-circuiting while removing the extra interface-pack forwarding instantiation.
Assisted-by: Codex
---
Full diff: https://github.com/llvm/llvm-project/pull/233051.diff
3 Files Affected:
- (modified) mlir/include/mlir/IR/OpDefinition.h (+20-7)
- (modified) mlir/include/mlir/Support/InterfaceSupport.h (+8-19)
- (modified) mlir/lib/Support/InterfaceSupport.cpp (+14)
``````````diff
diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h
index 0ab6679187c8eb..38cd7da8495e19 100644
--- a/mlir/include/mlir/IR/OpDefinition.h
+++ b/mlir/include/mlir/IR/OpDefinition.h
@@ -1643,7 +1643,12 @@ foldTrait(Operation *, ArrayRef<Attribute>, SmallVectorImpl<OpFoldResult> &) {
template <typename... Ts>
LogicalResult foldTraits(Operation *op, ArrayRef<Attribute> operands,
SmallVectorImpl<OpFoldResult> &results) {
- return success((succeeded(foldTrait<Ts>(op, operands, results)) || ...));
+ // Reuse one no-op specialization for traits without a folder.
+ return success(
+ (succeeded(
+ foldTrait<std::conditional_t<detect_has_any_fold_trait<Ts>::value,
+ Ts, void>>(op, operands, results)) ||
+ ...));
}
//===----------------------------------------------------------------------===//
@@ -1676,7 +1681,11 @@ LogicalResult verifyTrait(Operation *op) {
/// Given a set of traits, return the result of verifying the given operation.
template <typename... Ts>
LogicalResult verifyTraits(Operation *op) {
- return success((succeeded(verifyTrait<Ts>(op)) && ...));
+ // Avoid instantiating an identical no-op verifier for each absent hook.
+ return success(
+ (succeeded(verifyTrait<std::conditional_t<
+ detect_has_verify_trait<Ts>::value, Ts, void>>(op)) &&
+ ...));
}
/// Verify the given trait if it provides a region verifier.
@@ -1692,7 +1701,12 @@ LogicalResult verifyRegionTrait(Operation *op) {
/// given operation.
template <typename... Ts>
LogicalResult verifyRegionTraits(Operation *op) {
- return success((succeeded(verifyRegionTrait<Ts>(op)) && ...));
+ // Avoid instantiating an identical no-op verifier for each absent hook.
+ return success(
+ (succeeded(
+ verifyRegionTrait<std::conditional_t<
+ detect_has_verify_region_trait<Ts>::value, Ts, void>>(op)) &&
+ ...));
}
} // namespace op_definition_impl
@@ -2135,10 +2149,9 @@ class Op : public OpState, public Traits<ConcreteType>... {
}
static constexpr bool hasNoDataMembers() {
- // Checking that the derived class does not define any member by comparing
- // its size to an ad-hoc EmptyOp.
- class EmptyOp : public Op<EmptyOp, Traits...> {};
- return sizeof(ConcreteType) == sizeof(EmptyOp);
+ // Compare with the existing base instead of instantiating the traits again
+ // for an otherwise unused operation type.
+ return sizeof(ConcreteType) == sizeof(Op);
}
/// Allow access to internal implementation methods.
diff --git a/mlir/include/mlir/Support/InterfaceSupport.h b/mlir/include/mlir/Support/InterfaceSupport.h
index 8ab691454f64b8..3d3690503f33ba 100644
--- a/mlir/include/mlir/Support/InterfaceSupport.h
+++ b/mlir/include/mlir/Support/InterfaceSupport.h
@@ -171,17 +171,9 @@ class InterfaceMap {
public:
InterfaceMap() = default;
- InterfaceMap(InterfaceMap &&) = default;
- InterfaceMap &operator=(InterfaceMap &&rhs) {
- for (auto &it : interfaces)
- free(it.second);
- interfaces = std::move(rhs.interfaces);
- return *this;
- }
- ~InterfaceMap() {
- for (auto &it : interfaces)
- free(it.second);
- }
+ InterfaceMap(InterfaceMap &&);
+ InterfaceMap &operator=(InterfaceMap &&rhs);
+ ~InterfaceMap();
/// Construct an InterfaceMap with the given set of template types. For
/// convenience given that object trait lists may contain other non-interface
@@ -195,7 +187,11 @@ class InterfaceMap {
return InterfaceMap();
} else {
InterfaceMap map;
- map.insertPotentialInterfaces<Types...>();
+ // A comma fold registers interfaces in source order. All non-interface
+ // traits share the same no-op specialization.
+ (map.insertPotentialInterface<std::conditional_t<
+ detect_get_interface_id<Types>::value, Types, void>>(),
+ ...);
return map;
}
}
@@ -217,13 +213,6 @@ class InterfaceMap {
}
private:
- /// Insert the given interface types in source order. A comma fold is
- /// sequenced left to right in C++17.
- template <typename... Types>
- void insertPotentialInterfaces() {
- (insertPotentialInterface<Types>(), ...);
- }
-
/// Insert the given interface type into the map, ignoring it if it doesn't
/// actually represent an interface.
template <typename T>
diff --git a/mlir/lib/Support/InterfaceSupport.cpp b/mlir/lib/Support/InterfaceSupport.cpp
index 4f321457dd2c88..32312c1abbfc67 100644
--- a/mlir/lib/Support/InterfaceSupport.cpp
+++ b/mlir/lib/Support/InterfaceSupport.cpp
@@ -18,6 +18,20 @@
using namespace mlir;
+detail::InterfaceMap::InterfaceMap(InterfaceMap &&) = default;
+
+detail::InterfaceMap &detail::InterfaceMap::operator=(InterfaceMap &&rhs) {
+ for (auto &it : interfaces)
+ free(it.second);
+ interfaces = std::move(rhs.interfaces);
+ return *this;
+}
+
+detail::InterfaceMap::~InterfaceMap() {
+ for (auto &it : interfaces)
+ free(it.second);
+}
+
void detail::InterfaceMap::insert(TypeID interfaceId, void *conceptImpl) {
// Insert directly into the right position to keep the interfaces sorted.
auto *it =
``````````
</details>
https://github.com/llvm/llvm-project/pull/233051
More information about the Mlir-commits
mailing list