Conversion vs. transformation pass

Is there a best-practices in MLIR to decide whether a pass is a conversion pass or a transformation pass? This came up in a review with @kiranchandramohan here: ⚙ D103325 [mlir][openacc] Add conversion for if operand to scf.if for standalone data operation

Have you seen the glossary definition for a conversion?

Yes. I guess in our case we have then a conversion (OpenACC → OpenACC + SCF). So I guess conversion and transformation are a same thing right? conversion vs. translation of course are something different.

To me, every conversion is a transformation but it isn’t reciprocal. For example affine loop fusion is a transformation, but definitely not a conversion.

Ok this makes sense with this example.

Would it be possible to add an entry for Transformation as well?

I kind of feel that the affine loop fusion example fits the definition of Conversion in the glossary.
“The transformation of code represented in one dialect into a semantically equivalent representation in
… the same dialect (i.e. intra-dialect conversion).”

I think the term “conversion” has become overloaded and may deserve a clarification. There are several different uses:

  1. a pass that lives in lib/Conversion;
  2. a user of the dialect conversion infrastructure;
  3. a pass that replaces a subset of operations from dialects A,B,C… with operations from dialects D,E,F,…

These three items are often but not always used together. We can replace operations from one dialect with operations from another dialect without using the dialect conversion infrastructure.

The reason why lib/Conversion exists is library layering. A pass accepting dialect A and producing dialect B would need to depend on both dialects. If it had been put in the library of dialect A, it would create a dependency on dialect B from dialect A for no other reason than having this pass. This is expensive and increases the risk of circular dependencies that are hard to track (dialect A may depend on dialect D, which depends on C, which depends on A). However, if dialect A already depends on dialect B, e.g. because it uses its types, the conversion could live within dialect A.

Dialect conversion is currently a misnomer. It is just a piece of infrastructure that supports rewrite patterns that change the types of operation results (unlike the greedy pattern rewriter), and has more advanced control over conversion process thanks to pattern benefits and dynamic legality rules. Historically, it was converting from operations using types from dialect A to operations using types from dialect B, hence the name. However, it can and is being used in passes that don’t leave the boundaries of one dialect and wouldn’t qualify as conversion using the current definition.

I usually classify as conversion any IR modification that replaces operations of one “kind” with operations of another “kind” while preserving the same semantics, where “kind” is a loosely defined group of semantically similar operations. For example, I wouldn’t call loop fusion a conversion because it keeps exactly the same kinds of operations as it received on input, there may be just fewer operations than before. Similarly, loop parallelization is not a conversion because it introduces semantics (parallelism) that wasn’t there before. On the contrary, replacing loops with a CFG of basic blocks is a conversion because the semantics is strictly the same. Canonicalization is where it gets tricky because it may replace operations with other operations, e.g. for strength reduction, but I consider those operations to be of the same “kind”.

A transformation in my opinion is literally any modification of the IR, it may not necessarily even be a pass, although most often it is. Conversions are a subset of transformations.


@ftynse : please send a patch to the FAQ :slight_smile:

I would say it reflects the main intent, you can use it for “non-conversion” transformations but is it common?

I agree about the intent. FWIW, it’s the “dialect” part rather than “conversion” that feels ill-suited. The infrastructure doesn’t seem widely used for “non-conversion” transformations, but the causal link is not established. It may be rarely used because it is assumed to be for “conversions” only. :slight_smile:

1 Like