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.