cornell-zhang/hcl-dialect

[Backend] `unrealized_conversion_cast` to be supported or removed

Closed this issue · 3 comments

Currently we use unrealized_conversion_cast to cast data from hcl.Fixed or hcl.UFixed to native MLIR types, but it seems the LLVM backend has not correctly handle it. The following test case comes from test_dtype.py/test_dtype_cast.

module {
  func @top(%arg0: memref<100xi1>, %arg1: memref<100xi1>) -> (memref<100x!hcl.UFixed<4, 2>>, memref<100x!hcl.UFixed<4, 2>>) attributes {extra_itypes = "us", extra_otypes = "__"} {
    %0 = memref.alloc() {name = "compute_18"} : memref<100x!hcl.UFixed<4, 2>>
    %1 = hcl.create_loop_handle "x" : !hcl.LoopHandle
    affine.for %arg2 = 0 to 100 {
      %6 = affine.load %arg0[%arg2] {from = "compute_16", unsigned} : memref<100xi1>
      %7 = affine.load %arg1[%arg2] {from = "compute_17"} : memref<100xi1>
      %8 = arith.addi %6, %7 {unsigned} : i1
      %9 = builtin.unrealized_conversion_cast %8 : i1 to !hcl.UFixed<4, 2>
      affine.store %9, %0[%arg2] {to = "compute_18"} : memref<100x!hcl.UFixed<4, 2>>
    } {loop_name = "x", stage_name = "compute_18"}
    %2 = hcl.create_stage_handle "compute_18" : !hcl.StageHandle
    %3 = memref.alloc() {name = "compute_19"} : memref<100x!hcl.UFixed<4, 2>>
    %4 = hcl.create_loop_handle "x" : !hcl.LoopHandle
    affine.for %arg2 = 0 to 100 {
      %6 = affine.load %arg0[%arg2] {from = "compute_16", unsigned} : memref<100xi1>
      %7 = affine.load %arg1[%arg2] {from = "compute_17"} : memref<100xi1>
      %8 = arith.subi %6, %7 {unsigned} : i1
      %9 = builtin.unrealized_conversion_cast %8 : i1 to !hcl.UFixed<4, 2>
      affine.store %9, %3[%arg2] {to = "compute_19"} : memref<100x!hcl.UFixed<4, 2>>
    } {loop_name = "x", stage_name = "compute_19"}
    %5 = hcl.create_stage_handle "compute_19" : !hcl.StageHandle
    return %0, %3 : memref<100x!hcl.UFixed<4, 2>>, memref<100x!hcl.UFixed<4, 2>>
  }
}

This causes the following bug.

loc("-":9:7): error: failed to legalize operation 'affine.store'
loc("-":2:3): error: cannot be converted to LLVM IR: missing `LLVMTranslationDialectInterface` registration for dialect for op: builtin.func

Maybe we should think about whether we should add our own cast operation in hcl dialect, or just support some cases of unrealized_conversion_cast in LLVM. @zzzDavid

I think this is because we haven't supported casting from/to fixed/ufixed data type, I'll add support for this

To avoid any unrealized_cast_op, I think we need to support all-to-all cast of all data types.

The cast operations we already have:

  • Index to signless integer
  • Float <--> Signed/Unsigned Int
  • Int truncation, signed/unsigned extension
  • Float truncation, extension

We need to add support for the following cast operations:

  • Signed/Unsigned fixed point <--> signed/unsigned integer
  • Signed/Unsigned fixed point <--> float
  • Cast between any two fixed-point types

By 46bee97, all unrealized_cast_op is deprecated, and the test cases in mlir/test_dtype.py::test_dtype_cast all passed