A comprehensive proposal for using CRTP (Curiously Recurring Template Pattern) as an alternative to TableGen for defining MLIR operations, offering enhanced flexibility, lower learning barrier, and better development experience.
MLIR Community Discussion : rfc-modern-c-alternative-to-tablegen-for-mlir-operation-definition
The key innovation: Users can control and modify framework behavior from their own scope without modifying any framework code.
- Code Non-Invasive: Zero changes to framework source code
- Functionality Invasive: Complete control over framework behavior
- Implementation: Declarative trait binding controls the base class of framework operations
This approach inverts the traditional extension model - instead of the framework providing fixed extension points, users declare what they want, and the framework adapts automatically without any code enhancement.
- Understanding this approach's implementation principles and various usage patterns with AI assistance can significantly accelerate the process of familiarizing with this approach and exploring more possible extension usages.
- Possible AI prompts: -- "Explain CRTP patterns in MLIR operation definition" -- "Compare TableGen vs CRTP approaches for framework extension" -- "Help me understand the 'non-invasive code, invasive functionality' design philosophy" -- "How does this approach control and modify framework behavior without modifying MLIR framework code" -- "Analyze the trait_binding mechanism in this CRTP proposal" -- "I have this requirement (xxx), how can I use this approach's techniques to solve it"
Error/Exception Handling: This project's demonstration code focuses on showcasing core technical concepts and essential functionality. For clarity and to highlight key points, detailed error handling (boundary checks, exception handling, etc.) has been omitted. Please add appropriate error handling mechanisms in production environments.
Instead of generating C++ from DSL, write C++ directly with modern patterns:
// Traditional TableGen approach
def AddOp : Op<"add", [Commutative]> {
let hasFolder = 1; // Limited to predefined extension pointsl
}
// Generates ~200 lines of C++ code
// CRTP approach
template<> struct trait_binding<AddOp> : Type2Type<ArithmeticTrait<AddOp>> {};
class AddOp : public Op<AddOp> {
// Automatically inherits ArithmeticTrait capabilities
// Can override any base class method
// Can add custom methods
};
// ~15 lines total, direct C++ code
Aspect | TableGen | CRTP Approach |
---|---|---|
Learning Curve | New DSL syntax | Standard C++ patterns |
Customization | Fixed extension points | Any method overridable |
Code Generation | 200+ lines per op | 0 lines generated |
IDE Support | Limited | Full C++ tooling |
Debugging | Generated code | Your actual code |
Template Support | Basic | Full C++ templates |
Performance | Zero overhead | Zero overhead |
git clone https://github.com/shenxiaolong-code/mlir-crtp-proposal
cd mlir-crtp-proposal
cd test
# Method 1: Use Makefile (recommended)
make all # Build all demos
make test # Run advanced value-binding demo
make help # Show all available targets
# Method 2: Manual compilation
g++ -std=c++17 base_crtp_demo.cpp -o base_demo && ./base_demo
g++ -std=c++17 enhanced_crtp_trait_bind_demo.cpp -o enhanced_demo && ./enhanced_demo
g++ -std=c++17 advanced_bind_demo.cpp -o advanced_demo && ./advanced_demo
The demos showcase:
- Selective Override: Implement only what you need
- Trait Binding: Declarative trait application
- Compile-time Safety: Full type checking and optimization
template<typename Derived>
class OpBase {
public:
// Unified interface - always delegates to derived
auto getInput() { return derived()->default_getInput(); }
bool verify() { return derived()->default_verify(); }
// Default implementations - selectively overridable
auto default_getInput() { /* framework default */ }
bool default_verify() { return true; }
private:
Derived* derived() { return static_cast<Derived*>(this); }
};
// Framework provides intelligent defaults
template<typename T>
struct trait_binding : Type2Type<DefaultTrait<T>> {};
// Users declaratively specify replacements
template<> struct trait_binding<AddOp> : Type2Type<ArithmeticTrait<AddOp>> {};
template<> struct trait_binding<LoadOp> : Type2Type<MemoryTrait<LoadOp>> {};
// Operations automatically inherit appropriate traits
class AddOp : public Op<AddOp> {
// Gets ArithmeticTrait capabilities automatically
};
mlir-crtp-proposal/
βββ README.md # English version (this file)
βββ README_cn.md # Chinese version
βββ LICENSE # MIT License
βββ MLIR_CRTP_RFC_Proposal.md # Complete technical RFC (English)
βββ MLIR_CRTP_RFC_Proposal_cn.md # Complete technical RFC (Chinese)
βββ base_crtp_demo.cpp # Basic CRTP patterns
βββ base_crtp_demo.md # Basic demo guide (English)
βββ base_crtp_demo_cn.md # Basic demo guide (Chinese)
βββ enhanced_crtp_trait_bind_demo.cpp # Full trait_binding system
βββ enhanced_crtp_trait_bind_demo.md # Enhanced demo guide (English)
βββ enhanced_crtp_trait_bind_demo_cn.md # Enhanced demo guide (Chinese)
base_crtp_demo.md
- Introduction to CRTP patternsenhanced_crtp_trait_bind_demo.md
- Complete trait_binding systemadvanced_bind_from_value_to_type.md
- π₯ Industrial type-to-value-binding techniquesMLIR_CRTP_RFC_Proposal.md
- Comprehensive technical proposal
- Lower Learning Barrier: Based on standard C++ patterns, no need to learn additional TableGen DSL
- Complete Flexibility: Override any method, not just extension points
- Non-invasive Design: Framework unchanged, users add specializations
- Type Safety: Compile-time trait detection and verification
- Modern C++: Template specialization, constexpr, concepts
- π Advanced Value Binding: Symbol optimization techniques (proof-of-concept stage)
- π₯ Symbol Table Reduction: Theoretical analysis shows significant reduction in MLIR template bloat (requires validation)
- π¨ Advanced Type Computation: Using MiniMPL template metaprogramming techniques
The performance advantages in this project are primarily based on:
- Theoretical Analysis: Based on C++ template mechanism's compile-time optimization characteristics
- Proof of Concept: Test results from small-scale demonstration code
- Requires Validation: Large-scale real project performance remains to be verified
Benchmarking in actual projects is recommended to verify specific performance benefits.
Our approach leverages template metaprogramming techniques from the MiniMPL TypeList library, enabling:
- Industrial-Grade Type Manipulation: Advanced algorithms for compile-time type operations
- Dynamic Dialect Generation: Automatic creation of operation variants through type transformations
- Compile-Time Optimization: Zero runtime overhead with sophisticated compile-time dispatch
Instead of complex conditional logic:
// Clean traits hierarchy
template<BinaryOpKind Kind> struct BinaryOpTraits;
template<> struct BinaryOpTraits<BinaryOpKind::Add> {
static constexpr const char* name = "add";
static constexpr bool commutative = true;
};
template<> struct BinaryOpTraits<BinaryOpKind::Sub> {
static constexpr const char* name = "sub";
static constexpr bool commutative = false;
};
template<typename OpType>
void analyzeOperation(OpType& op) {
if constexpr (OpType::template hasTrait<ArithmeticTrait<OpType>>()) {
op.getTrait()->fold(); // Only compiled for arithmetic ops
}
if constexpr (OpType::template hasTrait<MemoryTrait<OpType>>()) {
op.getTrait()->getMemorySlots(); // Only compiled for memory ops
}
}
- Zero Code Generation: Direct C++ means no intermediate generated code
- Better Development Experience: Full IDE support, direct debugging, standard refactoring
- Modern C++ Features: Template specialization, constexpr, concepts, etc.
- Gradual Migration: Can coexist with TableGen during transition
- Community Familiarity: Every MLIR developer already knows C++
This project welcomes contributions! Whether you're interested in:
- Extending the demo implementations
- Improving documentation
- Testing with real MLIR dialects
- Performance benchmarking
- Migration tooling development
Please feel free to submit issues, pull requests, or start discussions.
This proposal is part of an ongoing discussion in the MLIR community. For detailed technical analysis and community feedback:
- LLVM Discourse: RFC Discussion Thread
- GitHub Issues: Technical questions and feature requests
- Pull Requests: Code improvements and extensions
This project is licensed under the MIT License - see the LICENSE file for details.
- MLIR Community: For building an excellent infrastructure
- LLVM Project: For providing the foundation
- Modern C++ Community: For advancing template metaprogramming techniques
π Links