Thanks @ftynse for the comprehensive answer. I found the two different attributes operand_segment_sizes
and result_segment_sizes
in the MLIR Code. And they indeed appear in the generic pretty-printing, e.g, here.
A segment (or a list of segments for VariadicOfVariadic
, but there can be only one) is associated with the named definition in ODS.
What can be only one? Do you mean each operation can only have a single VariadicOfVariadic
argument?
The lengths of each portion is stored in the operand|result_segment_sizes
attribute of DenseI64ArrayAttr
type.
Originally, I was left wondering how you would store lengths of each single subrange of a VariadicOfVariadic
operand. However, I found the solution in the MLIR code. You have to specify another attribute that contains the single lengths of the VariadicOfVariadic
.
For any future readers, here an example
func.func @main() -> () {
^start:
%flag = arith.constant 1 : i32
%a = arith.constant 10 : i32
%b = arith.constant 11 : i32
cf.switch %flag : i32, [
default: ^end,
1: ^bb0(%a : i32),
2: ^bb1(%a, %b : i32, i32)
]
^bb0(%a0: i32):
func.return
^bb1(%a1: i32, %b1: i32):
func.return
^end():
func.return
}
can be turned into the following generic IR by running mlir-opt -mlir-print-op-generic ./sample.mlir
"builtin.module"() ({
"func.func"() ({
%0 = "arith.constant"() {value = 1 : i32} : () -> i32
%1 = "arith.constant"() {value = 10 : i32} : () -> i32
%2 = "arith.constant"() {value = 11 : i32} : () -> i32
"cf.switch"(%0, %1, %1, %2)[^bb3, ^bb1, ^bb2] {case_operand_segments = dense<[1, 2]> : tensor<2xi32>, case_values = dense<[1, 2]> : vector<2xi32>, operand_segment_sizes = dense<[1, 0, 3]> : vector<3xi32>} : (i32, i32, i32, i32) -> ()
^bb1(%3: i32): // pred: ^bb0
"func.return"() : () -> ()
^bb2(%4: i32, %5: i32): // pred: ^bb0
"func.return"() : () -> ()
^bb3: // pred: ^bb0
"func.return"() : () -> ()
}) {function_type = () -> (), sym_name = "main"} : () -> ()
}) : () -> ()