Mapping results of converted operation into operands of users of original result

I’m thinking of converting single illegal operation into set of multiple legal operations, as documented in ‘ConversionPass’.

It seems converted operation can have different number of arguments as long as type converter supports transformation of single type to set of multiple types.

/// size of 'operands' can be different with number of input arguments of 'op'
virtual LogicalResult
  matchAndRewrite(Operation *op, ArrayRef<Value> operands,
                  ConversionPatternRewriter &rewriter) const;

However, I wonder how converter knows which value in converted IR should be mapped to operands after conversion.

For example, let’s say original operation had one argument, which receives composite type called ‘StructType{x : I32, y : I64}’. After conversion, converted operation receives ‘I32’ and ‘I64’ as different argument, so it receives two arguments.

// Before conversion
%a = foo.createStruct [3:I32, 5:I64] : struct<I32, I64>
%res = foo.someOperation (%a : struct<I32, I64>) : I32

// After conversion
// 'createStruct' has been converted to two constant operations
%a_0 = bar.constant [3 : I32] : I32
%a_1 = bar.constant [5 : I64] : I64

// 'someOperation' has been converted to operation receiving two operands'
// Who tells converter to put %a_0 to first arg, and a_1 to second arg?
%res = bar.someOperation(%a_0 : I32, %a_1:I64) : I32

Now, how does MLIR know ‘a_0’ should be the first argument and ‘a_1’ should be the second? I guess ‘Type materialization’ should do the job, but it seems target materialization can only convert from range of values into single value, rather than converting single value to range of values.

Different doesn’t necessarily mean greater than. I also don’t seem a comment indicating what you quoted above, would you mind pointing me to it?

For 1->N type conversions, there is a specialized converter
and a pattern class that is provided with the mapping in its rewrite call.

2 Likes

I had a deep dive into ‘OneToNTypeConverter’ and ‘OneToNPatternRewriter’ from the source, and had a look into ‘TestOneToNTypeConversionPass’ to see example of using it. Now I think I understand what’s happening under the hood.

So, mlir uses those type converters to accept decomposed operands for composite types (such as tuple, structs… etc) and uses materialization functions to map original value to converted values, and vice versa.

What I looked into before was composite type example in toy tutorial (which uses fold function to remove struct access operation and composite type). It would’ve been nice If type converter was explained little more in toy tutorial (It may make the tutorial too complicated though).

It may belong to more than a “beginner” tutorial indeed. What we likely need are some “cookbook” or some specific tutorial that would dive on one topic. For example a tutorial on “all aspects of Dialect Conversion by examples” (any volunteer?)