Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MLIR #1

Open
9 of 14 tasks
tucan9389 opened this issue Apr 29, 2023 · 11 comments
Open
9 of 14 tasks

Support MLIR #1

tucan9389 opened this issue Apr 29, 2023 · 11 comments
Assignees

Comments

@tucan9389
Copy link
Owner

tucan9389 commented Apr 29, 2023

TODO

Runnable ratio with mlir.Parser and mlir.Tokenizer

Update at 23.05.10

repo name tensorflow mlir-hlo openxla/iree llvm-project llvm/circt
# of mlir files 1.5k 4.4k 1.1k 1.3k 500
success ratio 0.523 0.049 0.088 0.106 0.044

netron term vs. MLIR term

netron term MLIR term Graph term Note
mlir.Graph Region or Function Graph or Model
mlir.Parameter Value (Operation's Operand or Result) Edge
mlir.Argument Value (Operation's Operand or Result) Edge
mlir.Node Operation Node
mlir.Attributes Operation's Attribute Node's metadata
mlir.Tensor Constant Operation Kind of node
mlir.TensorType Edge's metadata
mlir.TensorShape Edge's metadata

MLIR graph structure

image

netron graph structure

image

Test the mlir.Parser and mlir.Tokenizer

Add following code bottom of the source/mlir.js and run node source/mlir.js.

const input = `
func.func @main(%arg0: f32) -> f32 {
    %result:2 = "foo_div"() : () -> (f32, i32)

    // Pretty form that defines a unique name for each result.
    %foo, %bar = "foo_div"() : () -> (f32, i32)

    // Invoke a TensorFlow function called tf.scramble with two inputs
    // and an attribute "fruit" stored in properties.
    %2 = "tf.scramble"(%result#0, %bar) <{fruit = "banana"}> : (f32, i32) -> f32

    // Invoke an operation with some discardable attributes
    %foo2, %bar2 = "foo_div"() {some_attr = "value", other_attr = 42 : i64} : () -> (f32, i32)

    return %bar2: f32
}
`

const decoder = text.Decoder.open(input);
const parser = new mlir.Parser(decoder);
const obj = parser.read();
console.log(JSON.stringify(obj, null, 2));

cc. @chococigar

@tucan9389 tucan9389 self-assigned this Apr 29, 2023
@tucan9389
Copy link
Owner Author

tucan9389 commented Apr 29, 2023

Example MLIR (stablehlo_sample.mlir)

https://github.com/openxla/stablehlo/blob/main/docs/spec.md

stablehlo.func @main(
  %image: tensor<28x28xf32>,
  %weights: tensor<784x10xf32>,
  %bias: tensor<1x10xf32>
) -> tensor<1x10xf32> {
  %0 = "stablehlo.reshape"(%image) : (tensor<28x28xf32>) -> tensor<1x784xf32>
  %1 = "stablehlo.dot"(%0, %weights) : (tensor<1x784xf32>, tensor<784x10xf32>) -> tensor<1x10xf32>
  %2 = "stablehlo.add"(%1, %bias) : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32>
  %3 = "stablehlo.constant"() { value = dense<0.0> : tensor<1x10xf32> } : () -> tensor<1x10xf32>
  %4 = "stablehlo.maximum"(%2, %3) : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32>
  "stablehlo.return"(%4): (tensor<1x10xf32>) -> ()
}

@tucan9389
Copy link
Owner Author

🎊🎊 First MLIR graph

image

@tucan9389
Copy link
Owner Author

tucan9389 commented May 1, 2023

Examples

  • input: it's the content of the input file having .mlir extension
  • intermediate output: with the intermediate output, we can make the mlir.Graph and mlir.Node, etc. to visualize the graph

issue_1043.mlir (onnx dialect, 7 lines)

stablehlo_sample.mlir (stablehlo dialect, 14 lines)

examples.mnist_xla.mlir (tf dialect, mhlo dialect, 208 lines)

@tucan9389
Copy link
Owner Author

tucan9389 commented May 1, 2023

Test Inputs for mlir.Tokenizer

module attributes {tf.versions = {bad_consumers = [], min_consumer = 12 : i32, producer = 440 : i32}, tf_saved_model.semantics} {
"tf_saved_model.global_tensor"() {is_mutable, sym_name = "__sm_node4__optimizer.iter", tf_saved_model.exported_names = [], type = tensor<i64>, value = dense<0> : tensor<i64>} : () -> ()
    "tf_saved_model.global_tensor"() {sym_name = "__sm_node6__optimizer.learning_rate", tf_saved_model.exported_names = [], type = tensor<f32>, value = dense<0.00999999977> : tensor<f32>} : () -> ()
    func @__inference_predict_3320(%arg0: tensor<32x28x28x1xf32> {tf._user_specified_name = "inputs", tf_saved_model.index_path = [0]}, %arg1: tensor<32x1xf32> {tf._user_specified_name = "targets", tf_saved_model.index_path = [1]}, %arg2: tensor<!tf.resource<tensor<5x5x1x32xf32>>> {tf_saved_model.bound_input = @__sm_node17__model.conv1.kernel}, %arg3: tensor<!tf.resource<tensor<5x5x32x32xf32>>> {tf_saved_model.bound_input = @__sm_node26__model.conv2.kernel}, %arg4: tensor<!tf.resource<tensor<1568x1024xf32>>> {tf_saved_model.bound_input = @__sm_node39__model.dense1.kernel}, %arg5: tensor<!tf.resource<tensor<1024xf32>>> {tf_saved_model.bound_input = @__sm_node40__model.dense1.bias}, %arg6: tensor<!tf.resource<tensor<1024x10xf32>>> {tf_saved_model.bound_input = @__sm_node49__model.dense2.kernel}, %arg7: tensor<!tf.resource<tensor<10xf32>>> {tf_saved_model.bound_input = @__sm_node50__model.dense2.bias}, %arg8: tensor<!tf.resource<tensor<f32>>> {tf_saved_model.bound_input = @__sm_node6__optimizer.learning_rate}, %arg9: tensor<!tf.resource<tensor<i64>>> {tf_saved_model.bound_input = @__sm_node4__optimizer.iter}) -> (tensor<f32> {tf_saved_model.index_path = []}) attributes {tf._input_shapes = [#tf.shape<32x28x28x1>, #tf.shape<32x1>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>], tf.signature.is_stateful, tf_saved_model.exported_names = ["predict"]} {
        %0 = mhlo.constant dense<3.125000e-02> : tensor<32x10xf32>
        %0 = mhlo.constant dense<3.125000e-02> : tensor<32x10xf32>
      %1 = mhlo.constant dense<3.200000e+01> : tensor<f32>
      %2 = mhlo.constant dense<1> : tensor<i64>
      %14 = "tf.Cast"(%arg2) {Truncate = false} : (tensor<!tf.resource<tensor<5x5x1x32xf32>>>) -> tensor<!tf.resource>
    %27 = "mhlo.convolution"(%arg0, %22) {batch_group_count = 1 : i64, dimension_numbers = {input_batch_dimension = 0 : i64, input_feature_dimension = 3 : i64, input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, kernel_input_feature_dimension = 2 : i64, kernel_output_feature_dimension = 3 : i64, kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, output_batch_dimension = 0 : i64, output_feature_dimension = 3 : i64, output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, feature_group_count = 1 : i64, padding = dense<2> : tensor<2x2xi64>, rhs_dilation = dense<1> : tensor<2xi64>, window_strides = dense<1> : tensor<2xi64>} : (tensor<32x28x28x1xf32>, tensor<5x5x1x32xf32>) -> tensor<32x28x28x32xf32>
    %28 = mhlo.maximum %27, %11 : tensor<32x28x28x32xf32>
    %29 = "mhlo.reduce_window"(%28, %8) ( {
    ^bb0(%arg10: tensor<f32>, %arg11: tensor<f32>):  // no predecessors
      %130 = mhlo.maximum %arg10, %arg11 : tensor<f32>
      "mhlo.return"(%130) : (tensor<f32>) -> ()
    }) {padding = dense<0> : tensor<4x2xi64>, window_dimensions = dense<[1, 2, 2, 1]> : tensor<4xi64>, window_strides = dense<[1, 2, 2, 1]> : tensor<4xi64>} : (tensor<32x28x28x32xf32>, tensor<f32>) -> tensor<32x14x14x32xf32>
    %30 = "mhlo.convolution"(%29, %21) {batch_group_count = 1 : i64, dimension_numbers = {input_batch_dimension = 0 : i64, input_feature_dimension = 3 : i64, input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, kernel_input_feature_dimension = 2 : i64, kernel_output_feature_dimension = 3 : i64, kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, output_batch_dimension = 0 : i64, output_feature_dimension = 3 : i64, output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, feature_group_count = 1 : i64, padding = dense<2> : tensor<2x2xi64>, rhs_dilation = dense<1> : tensor<2xi64>, window_strides = dense<1> : tensor<2xi64>} : (tensor<32x14x14x32xf32>, tensor<5x5x32x32xf32>) -> tensor<32x14x14x32xf32>
    "tf.AssignVariableOp"(%20, %126) : (tensor<!tf.resource>, tensor<*xi64>) -> ()
    %127 = "mhlo.reduce"(%68, %12) ( {
    ^bb0(%arg10: tensor<f32>, %arg11: tensor<f32>):  // no predecessors
      %130 = mhlo.add %arg10, %arg11 : tensor<f32>
      "mhlo.return"(%130) : (tensor<f32>) -> ()
    }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<32xf32>, tensor<f32>) -> tensor<f32>
    %128 = mhlo.divide %127, %1 : tensor<f32>
    %129 = "mhlo.select"(%13, %12, %128) : (tensor<i1>, tensor<f32>, tensor<f32>) -> tensor<f32>
    return %129 : tensor<f32>
  }
}
// Compute A*B using an implementation of multiply kernel and print the
// result using a TensorFlow op. The dimensions of A and B are partially
// known. The shapes are assumed to match.
func.func @mul(%A: tensor<100x?xf32>, %B: tensor<?x50xf32>) -> (tensor<100x50xf32>) {
  // Compute the inner dimension of %A using the dim operation.
  %n = memref.dim %A, 1 : tensor<100x?xf32>

  // Allocate addressable "buffers" and copy tensors %A and %B into them.
  %A_m = memref.alloc(%n) : memref<100x?xf32>
  memref.tensor_store %A to %A_m : memref<100x?xf32>

  %B_m = memref.alloc(%n) : memref<?x50xf32>
  memref.tensor_store %B to %B_m : memref<?x50xf32:<>>

  // Call function @multiply passing memrefs as arguments,
  // and getting returned the result of the multiplication.
  %C_m = call @multiply(%A_m, %B_m)
          : (memref<100x?xf32>, memref<?x50xf32>) -> (memref<100x50xf32>)

  memref.dealloc %A_m : memref<100x?xf32>
  memref.dealloc %B_m : memref<?x50xf32>

  // Load the buffer data into a higher level "tensor" value.
  %C = memref.tensor_load %C_m : memref<100x50xf32>
  memref.dealloc %C_m : memref<100x50xf32>

  // Call TensorFlow built-in function to print the result tensor.
  "tf.Print"(%C){message: "mul result"} : (tensor<100x50xf32>) -> (tensor<100x50xf32>)

  return %C : tensor<100x50xf32>
}
module {
    
      func @my_function(%arg0: memref<32x32xf32>) attributes {affine_map_attr = affine_map<(d0, d1) -> (d0 + d1, d0 - d1)>} {
        // function body
      }
      func @my_function() attributes {array_attr = [1, 2, 3]} {
        // function body
      }
      func @my_function() attributes {nested_attr = {inner_attr1 = true, inner_attr2 = 3.14 : f64}} {
        // function body
      }
      func @my_function(%arg0: f32, %arg1: f32) -> f32 attributes {attr1 = "value", attr2 = 42 : i32, attr3 = dense<[1, 2, 3]> : tensor<3xi32>} {
        // function body
      }

      stablehlo.func @main(%image: tensor<28x28xf32>, %weights: tensor<784x10xf32>,%bias: tensor<1x10xf32>) -> tensor<1x10xf32> {
        %99 = "mhlo.broadcast_in_dim"(%41) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<5x5x32x32xf32>
        %98 = "mhlo.broadcast_in_dim"(%41) : (tensor<f32>) -> tensor<5x5x32x32xf32> {broadcast_dimensions = dense<> : tensor<0xi64>}
        "stablehlo.return"(%1): (tensor<1x10xf32>) -> ()
    }


      func @example(%arg1: i32, %arg2: i32) -> (i32) { }
    func @example(%arg1: i32, %arg2: i32) -> (i32, i32) { }
    func @example(%arg1: i32, %arg2: i32) -> i32 { }

    }
 module attributes {tf.versions = {bad_consumers = [], min_consumer = 12 : i32, producer = 440 : i32}, tf_saved_model.semantics} {
        "tf_saved_model.global_tensor"() {is_mutable, sym_name = "__sm_node4__optimizer.iter", tf_saved_model.exported_names = [], type = tensor<i64>, value = dense<0> : tensor<i64>} : () -> ()
        "tf_saved_model.global_tensor"() {sym_name = "__sm_node6__optimizer.learning_rate", tf_saved_model.exported_names = [], type = tensor<f32>, value = dense<0.00999999977> : tensor<f32>} : () -> ()
            func @__inference_predict_3320(%arg0: tensor<32x28x28x1xf32> {tf._user_specified_name = "inputs", tf_saved_model.index_path = [0]}, %arg1: tensor<32x1xf32> {tf._user_specified_name = "targets", tf_saved_model.index_path = [1]}, %arg2: tensor<!tf.resource<tensor<5x5x1x32xf32>>> {tf_saved_model.bound_input = @__sm_node17__model.conv1.kernel}, %arg3: tensor<!tf.resource<tensor<5x5x32x32xf32>>> {tf_saved_model.bound_input = @__sm_node26__model.conv2.kernel}, %arg4: tensor<!tf.resource<tensor<1568x1024xf32>>> {tf_saved_model.bound_input = @__sm_node39__model.dense1.kernel}, %arg5: tensor<!tf.resource<tensor<1024xf32>>> {tf_saved_model.bound_input = @__sm_node40__model.dense1.bias}, %arg6: tensor<!tf.resource<tensor<1024x10xf32>>> {tf_saved_model.bound_input = @__sm_node49__model.dense2.kernel}, %arg7: tensor<!tf.resource<tensor<10xf32>>> {tf_saved_model.bound_input = @__sm_node50__model.dense2.bias}, %arg8: tensor<!tf.resource<tensor<f32>>> {tf_saved_model.bound_input = @__sm_node6__optimizer.learning_rate}, %arg9: tensor<!tf.resource<tensor<i64>>> {tf_saved_model.bound_input = @__sm_node4__optimizer.iter}) -> (tensor<f32> {tf_saved_model.index_path = []}) attributes {tf._input_shapes = [#tf.shape<32x28x28x1>, #tf.shape<32x1>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>, #tf.shape<*>], tf.signature.is_stateful, tf_saved_model.exported_names = ["predict"]} {
                %0 = mhlo.constant dense<3.125000e-02> : tensor<32x10xf32>
                %0 = mhlo.constant dense<3.125000e-02> : tensor<32x10xf32>
              %1 = mhlo.constant dense<3.200000e+01> : tensor<f32>
              %2 = mhlo.constant dense<1> : tensor<i64>
              %14 = "tf.Cast"(%arg2) {Truncate = false} : (tensor<!tf.resource<tensor<5x5x1x32xf32>>>) -> tensor<!tf.resource>
            %27 = "mhlo.convolution"(%arg0, %22) {batch_group_count = 1 : i64, dimension_numbers = {input_batch_dimension = 0 : i64, input_feature_dimension = 3 : i64, input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, kernel_input_feature_dimension = 2 : i64, kernel_output_feature_dimension = 3 : i64, kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, output_batch_dimension = 0 : i64, output_feature_dimension = 3 : i64, output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, feature_group_count = 1 : i64, padding = dense<2> : tensor<2x2xi64>, rhs_dilation = dense<1> : tensor<2xi64>, window_strides = dense<1> : tensor<2xi64>} : (tensor<32x28x28x1xf32>, tensor<5x5x1x32xf32>) -> tensor<32x28x28x32xf32>
            %28 = mhlo.maximum %27, %11 : tensor<32x28x28x32xf32>
            %29 = "mhlo.reduce_window"(%28, %8) ( {
            ^bb0(%arg10: tensor<f32>, %arg11: tensor<f32>):  // no predecessors
              %130 = mhlo.maximum %arg10, %arg11 : tensor<f32>
              "mhlo.return"(%130) : (tensor<f32>) -> ()
            }) {padding = dense<0> : tensor<4x2xi64>, window_dimensions = dense<[1, 2, 2, 1]> : tensor<4xi64>, window_strides = dense<[1, 2, 2, 1]> : tensor<4xi64>} : (tensor<32x28x28x32xf32>, tensor<f32>) -> tensor<32x14x14x32xf32>
            %30 = "mhlo.convolution"(%29, %21) {batch_group_count = 1 : i64, dimension_numbers = {input_batch_dimension = 0 : i64, input_feature_dimension = 3 : i64, input_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>, kernel_input_feature_dimension = 2 : i64, kernel_output_feature_dimension = 3 : i64, kernel_spatial_dimensions = dense<[0, 1]> : tensor<2xi64>, output_batch_dimension = 0 : i64, output_feature_dimension = 3 : i64, output_spatial_dimensions = dense<[1, 2]> : tensor<2xi64>}, feature_group_count = 1 : i64, padding = dense<2> : tensor<2x2xi64>, rhs_dilation = dense<1> : tensor<2xi64>, window_strides = dense<1> : tensor<2xi64>} : (tensor<32x14x14x32xf32>, tensor<5x5x32x32xf32>) -> tensor<32x14x14x32xf32>
            "tf.AssignVariableOp"(%20, %126) : (tensor<!tf.resource>, tensor<*xi64>) -> ()
            %127 = "mhlo.reduce"(%68, %12) ( {
            ^bb0(%arg10: tensor<f32>, %arg11: tensor<f32>):  // no predecessors
              %130 = mhlo.add %arg10, %arg11 : tensor<f32>
              "mhlo.return"(%130) : (tensor<f32>) -> ()
            }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<32xf32>, tensor<f32>) -> tensor<f32>
            %128 = mhlo.divide %127, %1 : tensor<f32>
            %129 = "mhlo.select"(%13, %12, %128) : (tensor<i1>, tensor<f32>, tensor<f32>) -> tensor<f32>
            return %129 : tensor<f32>
          }
        }

@tucan9389
Copy link
Owner Author

tucan9389 commented May 4, 2023

no args, no parens operation

Done: be9a3df

// CHECK: use_two_sep_ops_empty_tensor_list
func.func @use_two_sep_ops_empty_tensor_list() {
  %one = "tf.Const"() {value = dense<1> : tensor<i32>} : () -> tensor<i32>
  %elem_shape = "tf.Const"() {value = dense<[-1, 1]> : tensor<2xi32>} : () -> tensor<2xi32>
  %size = "tf.Const"() {value = dense<10> : tensor<i32>} : () -> tensor<i32>
  // CHECK: EmptyTensorList
  // CHECK: EmptyTensorList
  // CHECK: EmptyTensorList
  %tl = "tf.EmptyTensorList"(%elem_shape, %size) : (tensor<2xi32>, tensor<i32>) -> tensor<!tf_type.variant<tensor<?x1xf32>>>
  %elem_1 = "tf._FirstOp"() : () -> tensor<8x1xf32>
  %tl_set_item = "tf.TensorListSetItem"(%tl, %one, %elem_1) : (tensor<!tf_type.variant<tensor<?x1xf32>>>, tensor<i32>, tensor<8x1xf32>) -> tensor<!tf_type.variant<tensor<?x1xf32>>>
  %elem_2 = "tf._SecondOp"() : () -> tensor<16x1xf32>
  %tl_set_item2 = "tf.TensorListSetItem"(%tl, %one, %elem_2) : (tensor<!tf_type.variant<tensor<?x1xf32>>>, tensor<i32>, tensor<16x1xf32>) -> tensor<!tf_type.variant<tensor<?x1xf32>>>
  func.return
}

@tucan9389
Copy link
Owner Author

tucan9389 commented May 4, 2023

while

Done: 1e06958

  • :integer-literal of op-result:
  • region-list: op_name ( args ) ({...}, {...}) : function-type
func.func @while_region_op_two_sep_args_empty_tensor_list() {
  %one = "tf.Const"() {value = dense<1> : tensor<i32>} : () -> tensor<i32>
  %elem_shape = "tf.Const"() {value = dense<[-1, 1]> : tensor<2xi32>} : () -> tensor<2xi32>
  %size = "tf.Const"() {value = dense<10> : tensor<i32>} : () -> tensor<i32>
  %tl = "tf.EmptyTensorList"(%elem_shape, %size) : (tensor<2xi32>, tensor<i32>) -> tensor<!tf_type.variant<tensor<?x1xf32>>>
  %while:2 = "tf.WhileRegion"(%tl, %tl) ({
    ^bb0(%barg1: tensor<!tf_type.variant<tensor<?x1xf32>>>, %barg2: tensor<!tf_type.variant<tensor<?x1xf32>>>): // no predeceessors
      %cond = "tf.false"():()-> tensor<i1>
      "tf.Yield"(%cond) : (tensor<i1>) -> ()
  }, {
    ^bb0(%barg1: tensor<!tf_type.variant<tensor<?x1xf32>>>, %barg2: tensor<!tf_type.variant<tensor<?x1xf32>>>): // no predeceessors
    "tf.Yield"(%barg1, %barg2) : (tensor<!tf_type.variant<tensor<?x1xf32>>>, tensor<!tf_type.variant<tensor<?x1xf32>>>) -> ()
  }) {is_stateless = false} : (tensor<!tf_type.variant<tensor<?x1xf32>>>, tensor<!tf_type.variant<tensor<?x1xf32>>>) -> (tensor<!tf_type.variant<tensor<?x1xf32>>>, tensor<!tf_type.variant<tensor<?x1xf32>>>)
  func.return
}

Done: 1e06958

// https://github.com/tensorflow/tensorflow/blob/2d9d9c053c51ae417c9abfd4e0ea903e447d6952/tensorflow/compiler/mlir/tensorflow/tests/hoist_loop_invariant.mlir#L19
func.func @hoist_loop_invariant(%arg0: tensor<i32>, %arg1: tensor<i32>) -> (tensor<i32>, tensor<i32>) {
  %cst_0 = "tf.Const"() { value = dense<1> : tensor<i32> } : () -> tensor<i32>
  %0:2 = "tf.WhileRegion"(%arg0, %arg1) ({
  ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>):
    %1 = "tf.OpA"() {is_stateless = true} : () -> tensor<i1>
    "tf.Yield"(%1) : (tensor<i1>) -> ()
  }, {
  ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>):
    %cst_1 = "tf.Const"() { value = dense<0> : tensor<i32> } : () -> tensor<i32>
    %1 = "tf.Add"(%cst_1, %cst_0) : (tensor<i32>, tensor<i32>) -> tensor<i32>
    %2 = "tf.Mul"(%1, %cst_1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
    %3 = "tf.AddV2"(%arg2, %1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
    %4 = "tf.Div"(%arg3, %2) : (tensor<i32>, tensor<i32>) -> tensor<i32>
    "tf.Yield"(%3, %4) : (tensor<i32>, tensor<i32>) -> ()
  }) {is_stateless = true, parallel_iterations = 10 : i64} : (tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>)
  return %0#0, %0#1 : tensor<i32>, tensor<i32>
}

@tucan9389
Copy link
Owner Author

tucan9389 commented May 5, 2023

sharp keyword

  • access for a variable having multiple variables (%result#0)
  • Attribute Value Aliases
  • Dialect Attribute Values

https://mlir.llvm.org/docs/LangRef/

access for a variable having multiple variables (%result#0)

%2 = "tf.scramble"(%result#0, %bar) <{fruit = "banana"}> : (f32, i32) -> f32

https://mlir.llvm.org/docs/LangRef/

Attribute Value Aliases

#map = affine_map<(d0) -> (d0 + 10)>

// Using the original attribute.
%b = affine.apply affine_map<(d0) -> (d0 + 10)> (%a)

// Using the attribute alias.
%b = affine.apply #map(%a)

https://mlir.llvm.org/docs/LangRef/

Dialect Attribute Values

// A string attribute.
#foo<string<"">>

// A complex attribute.
#foo<"a123^^^" + bar>
// A string attribute.
#foo.string<"">

https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/compiler/mlir/tensorflow/tests/decompose_reduce_dataset.mlir

// CHECK-LABEL: func @skip_noncompiled_reduce_dataset
func.func @skip_noncompiled_reduce_dataset(
      %arg0 : tensor<!tf_type.variant>,
      %arg1: tensor<i64>
    ) {
    // CHECK: tf.ReduceDataset
    %1 = "tf.ReduceDataset"(%arg0, %arg1) {
      Targuments = [],
      Tstate = [i64], device = "",
      f = @__reduce_func_0, f._tf_data_function = true,
      output_shapes = [#tf_type.shape<>],
      output_types = [i64], use_inter_op_parallelism = true } : (tensor<!tf_type.variant>, tensor<i64>) -> (tensor<i64>)
    func.return
}

@tucan9389
Copy link
Owner Author

tucan9389 commented May 5, 2023

various op syntax in MLIR Ref doc

https://mlir.llvm.org/docs/LangRef/

Done: cc5daab

// An operation that produces two results.
// The results of %result can be accessed via the <name> `#` <opNo> syntax.
%result:2 = "foo_div"() : () -> (f32, i32)

// Pretty form that defines a unique name for each result.
%foo, %bar = "foo_div"() : () -> (f32, i32)

// Invoke a TensorFlow function called tf.scramble with two inputs
// and an attribute "fruit" stored in properties.
%2 = "tf.scramble"(%result#0, %bar) <{fruit = "banana"}> : (f32, i32) -> f32

// Invoke an operation with some discardable attributes
%foo, %bar = "foo_div"() {some_attr = "value", other_attr = 42 : i64} : () -> (f32, i32)

@tucan9389
Copy link
Owner Author

tucan9389 commented May 5, 2023

block syntax in MLIR Ref doc

https://mlir.llvm.org/docs/LangRef/

func.func @simple(i64, i1) -> i64 {
^bb0(%a: i64, %cond: i1): // Code dominated by ^bb0 may refer to %a
  cf.cond_br %cond, ^bb1, ^bb2

^bb1:
  cf.br ^bb3(%a: i64)    // Branch passes %a as the argument

^bb2:
  %b = arith.addi %a, %a : i64
  cf.br ^bb3(%b: i64)    // Branch passes %b as the argument

// ^bb3 receives an argument, named %c, from predecessors
// and passes it on to bb4 along with %a. %a is referenced
// directly from its defining operation and is not passed through
// an argument of ^bb3.
^bb3(%c: i64):
  cf.br ^bb4(%c, %a : i64, i64)

^bb4(%d : i64, %e : i64):
  %0 = arith.addi %d, %e : i64
  return %0 : i64   // Return is also a terminator.
}

@tucan9389
Copy link
Owner Author

tucan9389 commented May 5, 2023

graph region in MLIR Ref doc

Done: cc5daab

"test.graph_region"() ({ // A Graph region
  %1 = "op1"(%1, %3) : (i32, i32) -> (i32)  // OK: %1, %3 allowed here
  %2 = "test.ssacfg_region"() ({
     %5 = "op2"(%1, %2, %3, %4) : (i32, i32, i32, i32) -> (i32) // OK: %1, %2, %3, %4 all defined in the containing region
  }) : () -> (i32)
  %3 = "op2"(%1, %4) : (i32, i32) -> (i32)  // OK: %4 allowed here
  %4 = "op3"(%1) : (i32) -> (i32)
}) : () -> ()

@tucan9389
Copy link
Owner Author

tucan9389 commented May 5, 2023

exclamation mark(!)

https://mlir.llvm.org/docs/LangRef/#type-aliases

Type Aliases

!avx_m128 = vector<4 x f32>

// Using the original type.
"foo"(%x) : vector<4 x f32> -> ()

// Using the type alias.
"foo"(%x) : !avx_m128 -> ()

https://mlir.llvm.org/docs/LangRef/#dialect-types

Dialect Aliases

// A tensorflow string type.
!tf<string>

// A type with complex components.
!foo<something<abcd>>

// An even more complex type.
!foo<"a123^^^" + bar>

https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/compiler/mlir/tensorflow/tests/decompose_reduce_dataset.mlir

func.func @single_state_single_dataset_type_no_arguments(
      %arg0: tensor<!tf_type.variant>,
      %arg1: tensor<i64>
    ) {
    %1 = "tf.ReduceDataset"(%arg0, %arg1) {
      Targuments = [],
      Tstate = [i64], device = "/job:localhost/replica:0/task:0/device:TPU:1",
      f = @__reduce_func_1, f._tf_data_function = true,
      output_shapes = [#tf_type.shape<>],
      output_types = [i64], use_inter_op_parallelism = true, _xla_compile_device_type="TPU"} : (tensor<!tf_type.variant>, tensor<i64>) -> (tensor<i64>)
    func.return
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant