cornell-zhang/hcl-dialect

[Pass] Operand does not dominate this use

zzzDavid opened this issue · 2 comments

This threads records some issues I met lowering reverse bit operation on LLVM backend.

The original program:

module {
  func @top(%arg0: memref<10xi8>, %arg1: memref<10xi8>) attributes {bit, itypes = "uu", otypes = ""} {
    affine.for %arg2 = 0 to 10 {
      %0 = affine.load %arg0[%arg2] {from = "compute_0", unsigned} : memref<10xi8>
      %1 = hcl.bit_reverse(%0 : i8) {unsigned}
      %2 = affine.load %arg1[%arg2] {from = "compute_1", unsigned} : memref<10xi8>
      %c7 = arith.constant 7 : index
      %c0 = arith.constant 0 : index
      hcl.set_slice(%2 : i8, %c7, %c0, %1 : i8)
      affine.store %2, %arg1[%arg2] {to = "compute_1", unsigned} : memref<10xi8>
    } {loop_name = "loop_0"}
    return
  }
}

I lowered hcl.bit_reverse as getting and setting each bit:

module {
  func @top_lowered(%arg0: memref<10xi8>, %arg1: memref<10xi8>) attributes {bit, itypes = "uu", otypes = ""} {
    affine.for %arg2 = 0 to 10 {
      %0 = affine.load %arg0[%arg2] {from = "compute_0", unsigned} : memref<10xi8>
      %const_8 = arith.constant 8 : index
      %const_0 = arith.constant 0 : i8
      %1 = arith.addi %0, %const_0 : i8
      affine.for %bit_idx = 0 to 8 {
        %bit = hcl.get_bit(%0 : i8, %bit_idx) -> i1
        %reverse_idx = arith.subi %const_8, %bit_idx : index
        hcl.set_bit(%1 : i8, %reverse_idx, %bit : i1)
      }
      %2 = affine.load %arg1[%arg2] {from = "compute_1", unsigned} : memref<10xi8>
      %c7 = arith.constant 7 : index
      %c0 = arith.constant 0 : index
      hcl.set_slice(%2 : i8, %c7, %c0, %1 : i8) // On this line the error occurs
      affine.store %2, %arg1[%arg2] {to = "compute_1", unsigned} : memref<10xi8>
    } {loop_name = "loop_0"}
    return
  }
}

But running this program with hcl-opt %s --lower-to-llvm, I get this error:

error: operand #0 does not dominate this use

My understanding is that, %1 is updated in the affine.for blocks, so the hcl.set_slice's usage of %1 is not dominated by %1 = arith.addi %0, %const_0 : i8

A solution to the dominance issue is to use a memref:

module {
  func @top_lowered(%arg0: memref<10xi8>, %arg1: memref<10xi8>) attributes {bit, itypes = "uu", otypes = ""} {
    affine.for %arg2 = 0 to 10 {
      %0 = affine.load %arg0[%arg2] {from = "compute_0", unsigned} : memref<10xi8>
      %const_8 = arith.constant 8 : index
      %const_0 = arith.constant 0 : index
      %res_memref = memref.alloc() : memref<1xi8>
      affine.for %bit_idx = 0 to 8 {
        %res = affine.load %res_memref[%const_0] : memref<1xi8>
        %bit = hcl.get_bit(%0 : i8, %bit_idx) -> i1
        %reverse_idx = arith.subi %const_8, %bit_idx : index
        hcl.set_bit(%res : i8, %reverse_idx, %bit : i1)
        affine.store %res, %res_memref[%const_0] : memref<1xi8>
      }
      %1 = affine.load %res_memref[%const_0] : memref<1xi8>
      %2 = affine.load %arg1[%arg2] {from = "compute_1", unsigned} : memref<10xi8>
      %c7 = arith.constant 7 : index
      %c0 = arith.constant 0 : index
      hcl.set_slice(%2 : i8, %c7, %c0, %1 : i8)
      affine.store %2, %arg1[%arg2] {to = "compute_1", unsigned} : memref<10xi8>
    } {loop_name = "loop_0"}
    return
  }
}