[transform_ext] Move populate_pattern op to dialects dir#81
[transform_ext] Move populate_pattern op to dialects dir#81
Conversation
Introduces op `transform_ext.populate_pattern TARGET_OP_KIND PAT_NAME PRIORITY` where patterns can be registered on `PopulatePatternOp` via its `name_to_pattern_rewrite` class member. Fixes #80.
a6b71bb to
302a972
Compare
|
@charithaintc, this fixes #80. We should be able to merge it when @fschlimb and @adam-smnk are up in the morning. (You can check out users/rolfmorel/fix-pattern-op in the meantime if you'd like to be unblocked today.) |
| def register_and_load(): | ||
| from . import transform_ext | ||
|
|
||
| transform_ext.register_and_load() |
There was a problem hiding this comment.
What's the benefit of this wrapper/indirection?
There was a problem hiding this comment.
Because there's already a PR which extends multiple (sub)dialects: https://github.com/llvm/lighthouse/pull/63/changes#diff-c806f5426817d17a93adc42142d8d36986989d6f11083732266d2a127bcf8d9c
The indirection is so we have to only call one function once we have obtained the ir.Context().
| def register_and_load(context=None): | ||
| TransformExtensionDialect.load() |
There was a problem hiding this comment.
As in the tuning PR, this is so to have a unified interface to accomplish the respective registering and loading across the different (sub)dialect extensions: https://github.com/llvm/lighthouse/pull/63/changes#diff-c806f5426817d17a93adc42142d8d36986989d6f11083732266d2a127bcf8d9c
|
Does this also act as a general registry i.e., allow to register all custom patterns in one module and make them accessible for direct use? |
| def populate_pattern( | ||
| pattern_name: str, op_kind: str, priority: int | ||
| ) -> PopulatePatternOp: | ||
| """Camelcase constructor for PopulatePatternOp.""" |
There was a problem hiding this comment.
| """Camelcase constructor for PopulatePatternOp.""" | |
| """snake_case constructor for PopulatePatternOp.""" |
| # A mapping from pattern names to their corresponding rewrite functions. | ||
| # This should be populated by the users of this operation. In effect serves | ||
| # as a registry for rewrite patterns that can be applied by this operation. | ||
| name_to_rewrite_pattern = {} |
There was a problem hiding this comment.
I find this rather weird. Filling a specific singleton (that I don't control) and referring to my entry later feels odd. Suggest to not use a pattern with logically uses a global/singleton. And I don't see what problem it solves.
There was a problem hiding this comment.
I feel that this could/should be auto-populated with what's available in lighthouse to skip manual registration.
There was a problem hiding this comment.
I don't see what problem it solves.
The previous approach conflates an op definition with an instance of that op. That is, if you want to use multiple op instances in the IR, it would attempt to overwrite the previous op definition registration.
In general, on-demand usage of the factory pattern is not suited to the (current) op registration mechanism. The registration method for Python-defined ops assumes that all ops of a dialect are to be registered at the same time, before any instances of them are created. Invoking the factory function during IR construction violates this (when we have multiple ops in a dialect).
This PR's approach is set up to "have our cake and eat it". That is, we have the upfront definition of the relevant op(s) and can adjust the patterns that can be invoked during IR construction. That is, by modifying PopulatePatternOp.name_to_rewrite_pattern.
If we want to go for dedicated transform_ext.apply_patterns.PAT1 and transform_ext.apply_patterns.PAT2, etc. ops via a factory method, let me know. We would need to adjust the code to try to keep people from invoking the factory method after other ops from the same dialect have already been registered.
There was a problem hiding this comment.
I don't know. It feels like an odd workaround. In my mind, what we should provide is something like
my_pattern = register_pattern("func.func", lambda op: ...)
apply_my_pattern(my_pattern)
Can we avoid accessing a dict and instead have a registration function outside the class? Also asking the user to care about the name/key of the patterns doesn't seem needed.
Note that in the MLIR C++ codebase, RewritePatterns are not invokable by name. If anything, the |
adam-smnk
left a comment
There was a problem hiding this comment.
I like the registry direction.
I think this provides greater flexibility and reduces duplication of explicit wrapper ops.
While it diverges from upstream (C++ driven) pattern registration, I can see potential benefits that make it worth exploring alternatives.
PR provides only initial skeleton but looks like a good starting point for further iterations.
thanks @rolfmorel |
Introduces op
transform_ext.populate_pattern PAT_NAME TARGET_OP_KIND PRIORITYwhere patterns can be registered onPopulatePatternOpvia itsname_to_pattern_rewriteclass member.Fixes #80.