11#pragma once
22
3+ #include < type_traits>
4+
35#include " mlir/IR/PatternMatch.h"
46#include " mlir/Interfaces/FunctionInterfaces.h"
57
@@ -39,23 +41,35 @@ static LogicalResult failIfFuncOpInterfaceHasAttr(Operation *op,
3941 return success ();
4042}
4143
44+ static LogicalResult checkPreconditions (Operation *op,
45+ PatternRewriter &rewriter,
46+ bool supportsDynamicShapes) {
47+ if (op->hasAttr (kDisablePatternAttrName ))
48+ return rewriter.notifyMatchFailure (op, " disabled by attribute." );
49+
50+ if (failIfFuncOpInterfaceHasAttr (op, kDisablePatternAttrName , rewriter)
51+ .failed ())
52+ return failure ();
53+
54+ if (!supportsDynamicShapes) {
55+ if (failIfDynamicShape (op, rewriter).failed ())
56+ return failure ();
57+ }
58+
59+ return success ();
60+ }
61+
4262template <typename OpTy, typename Child>
4363struct CheckedOpRewritePattern : public OpRewritePattern <OpTy> {
4464 using Base = OpRewritePattern<OpTy>;
4565 using Base::Base;
4666
4767 LogicalResult
4868 matchAndRewrite (OpTy op, PatternRewriter &rewriter) const override final {
49- LogicalResult res =
50- failIfFuncOpInterfaceHasAttr (op, kDisablePatternAttrName , rewriter);
51- if (res.failed ())
52- return res;
53-
54- if (!((Child *)this )->supportsDynamicShapes ()) {
55- LogicalResult res = failIfDynamicShape (op, rewriter);
56- if (res.failed ())
57- return res;
58- }
69+ if (checkPreconditions (op, rewriter,
70+ ((Child *)this )->supportsDynamicShapes ())
71+ .failed ())
72+ return failure ();
5973
6074 return ((Child *)this )->matchAndRewriteImpl (op, rewriter);
6175 }
@@ -71,22 +85,41 @@ struct CheckedOpTraitRewritePattern : public OpTraitRewritePattern<TraitType> {
7185 LogicalResult
7286 matchAndRewrite (Operation *op,
7387 PatternRewriter &rewriter) const override final {
74- LogicalResult res =
75- failIfFuncOpInterfaceHasAttr (op, kDisablePatternAttrName , rewriter);
76- if (res.failed ())
77- return res;
78-
79- if (!((Child *)this )->supportsDynamicShapes ()) {
80- auto res = failIfDynamicShape (op, rewriter);
81- if (res.failed ())
82- return res;
83- }
88+ if (checkPreconditions (op, rewriter,
89+ ((Child *)this )->supportsDynamicShapes ())
90+ .failed ())
91+ return failure ();
8492
8593 return ((Child *)this )->matchAndRewriteImpl (op, rewriter);
8694 }
8795
8896 bool supportsDynamicShapes () const { return false ; }
8997};
9098
99+ template <typename T, typename = void >
100+ struct has_supports_dynamic_shapes : std::false_type {};
101+
102+ template <typename T>
103+ struct has_supports_dynamic_shapes <
104+ T, std::void_t <decltype (std::declval<T>().supportsDynamicShapes())>>
105+ : std::true_type {};
106+
107+ template <typename PatternTy> struct CheckedPattern : public PatternTy {
108+ using PatternTy::PatternTy;
109+
110+ LogicalResult matchAndRewrite (Operation *op,
111+ PatternRewriter &rewriter) const override {
112+ bool supportsDynamic = false ;
113+ if constexpr (has_supports_dynamic_shapes<PatternTy>::value) {
114+ supportsDynamic = this ->supportsDynamicShapes ();
115+ }
116+
117+ if (checkPreconditions (op, rewriter, supportsDynamic).failed ())
118+ return failure ();
119+
120+ return PatternTy::matchAndRewrite (op, rewriter);
121+ }
122+ };
123+
91124} // namespace enzyme
92125} // namespace mlir
0 commit comments