module @"LSimple;" {
func.func @my_add(%arg0: i32, %arg1: i32) -> i32 {
%0 = arith.addi %arg0, %arg1 : i32
%1 = arith.muli %arg0, %0 : i32
%2 = arith.divsi %1, %arg1 : i32
%3 = MjolnIR.loadfield @"LSimple;" -> @test_field(0) : i16
MjolnIR.storefield %3 : i16, @"LSimple;" -> @test_field(0)
MjolnIR.nop
%4 = arith.cmpi ne, %0, %2 : i32
cf.cond_br %4, ^bb2(%2 : i32), ^bb1(%0 : i32)
^bb1(%5: i32): // pred: ^bb0
%6 = "MjolnIR.move"(%5) : (i32) -> i32
cf.br ^bb3(%6 : i32)
^bb2(%7: i32): // pred: ^bb0
MjolnIR.nop
MjolnIR.fallthrough ^bb3(%7 : i32)
^bb3(%8: i32): // 2 preds: ^bb1, ^bb2
MjolnIR.nop
return %8 : i32
}
}
digraph G {
compound = true;
subgraph cluster_1 {
v2 [label = " ", shape = plain];
label = "builtin.module : ())\n\nsym_name: \"LSimple;\"";
subgraph cluster_3 {
v4 [label = " ", shape = plain];
label = "";
subgraph cluster_5 {
v6 [label = " ", shape = plain];
label = "func.func : ())\n\nfunction_type: (i32, i32) -> i32\nsym_name: \"my_add\"";
subgraph cluster_7 {
v8 [label = " ", shape = plain];
label = "";
v9 [label = "arg0", shape = ellipse];
v10 [label = "arg1", shape = ellipse];
v11 [label = "arith.addi : (i32))\n", shape = ellipse];
v12 [label = "arith.muli : (i32))\n", shape = ellipse];
v13 [label = "arith.divsi : (i32))\n", shape = ellipse];
v14 [label = "MjolnIR.loadfield : (i16))\n\nfieldClass: @\"LSimple;\"\nfieldName: @test_field\nfieldRef: 0 : ui32", shape = ellipse];
v15 [label = "MjolnIR.storefield : ())\n\nfieldClass: @\"LSimple;\"\nfieldName: @test_field\nfieldRef: 0 : ui32", shape = ellipse];
v16 [label = "MjolnIR.nop : ())\n", shape = ellipse];
v17 [label = "arith.cmpi : (i1))\n\npredicate: 1 : i64", shape = ellipse];
v18 [label = "cf.cond_br : ())\n\noperand_segment_sizes: array<i32: 1, 1, 1>", shape = ellipse];
}
subgraph cluster_19 {
v20 [label = " ", shape = plain];
label = "";
v21 [label = "arg0", shape = ellipse];
v22 [label = "MjolnIR.move : (i32))\n", shape = ellipse];
v23 [label = "cf.br : ())\n", shape = ellipse];
}
subgraph cluster_24 {
v25 [label = " ", shape = plain];
label = "";
v26 [label = "arg0", shape = ellipse];
v27 [label = "MjolnIR.nop : ())\n", shape = ellipse];
v28 [label = "MjolnIR.fallthrough : ())\n", shape = ellipse];
}
subgraph cluster_29 {
v30 [label = " ", shape = plain];
label = "";
v31 [label = "arg0", shape = ellipse];
v32 [label = "MjolnIR.nop : ())\n", shape = ellipse];
v33 [label = "func.return : ())\n", shape = ellipse];
}
}
}
}
v9 -> v11 [label = "0", style = solid];
v10 -> v11 [label = "1", style = solid];
v9 -> v12 [label = "0", style = solid];
v11 -> v12 [label = "1", style = solid];
v12 -> v13 [label = "0", style = solid];
v10 -> v13 [label = "1", style = solid];
v14 -> v15 [label = "", style = solid];
v11 -> v17 [label = "0", style = solid];
v13 -> v17 [label = "1", style = solid];
v17 -> v18 [label = "0", style = solid];
v13 -> v18 [label = "1", style = solid];
v11 -> v18 [label = "2", style = solid];
v21 -> v22 [label = "", style = solid];
v22 -> v23 [label = "", style = solid];
v26 -> v28 [label = "", style = solid];
v31 -> v33 [label = "", style = solid];
}
I think it's psosible to write a MLIR pass that given a MjolnIR module, it dumps a .dot file for each function with the shape of a Control Flow Graph (CFG).