cornell-zhang / hcl-dialect

HeteroCL-MLIR dialect for accelerator design
https://cornell-zhang.github.io/heterocl/index.html
Other
37 stars 15 forks source link

[MLIR Limitation] CPU runner (JIT) generates incorrect result for left shift operation by operand bitwidth #169

Open zzzDavid opened 1 year ago

zzzDavid commented 1 year ago

This is a bug in MLIR's JIT compiler.

Test case

module {
    func.func private @printMemrefI32(%ptr : memref<*xi32>)

    func.func @top () -> () {
        // allocate a memref<1xi32> and store a constant 50 into it
        %0 = memref.alloc() : memref<1xi32>
        %1 = arith.constant 50 : i32
        affine.store %1, %0[0] : memref<1xi32>

        // load the value from memref and shift left for 32 bits
        %2 = affine.load %0[0] : memref<1xi32>
        %cst_32 = arith.constant 32 : i32
        %3 = arith.shli %2, %cst_32 : i32

        // store it back to memref
        affine.store %3, %0[0] : memref<1xi32>

        // print memref
        %casted_memref = memref.cast %0 : memref<1xi32> to memref<*xi32>
        call @printMemrefI32(%casted_memref) : (memref<*xi32>) -> ()

        return
    }
    func.func @main() -> () {
        call @top() : () -> ()
        return
    }
}

Use MLIR JIT CPU runner:

mlir-opt main.mlir \
    --lower-affine \
    --convert-scf-to-cf \
    --convert-cf-to-llvm \
    --convert-memref-to-llvm \
    --convert-arith-to-llvm \
    --convert-func-to-llvm \
    --reconcile-unrealized-casts \
| mlir-cpu-runner -e main --O1 \
    --entry-point-result=void \
    --shared-libs=/work/shared/users/phd/nz264/llvm-project/build/lib/libmlir_c_runner_utils.so \
    --shared-libs=/work/shared/users/phd/nz264/llvm-project/build/lib/libmlir_runner_utils.so

MLIR cpu runner prints 50, the correct result should be 0.

Use translate to llvm IR -> llc -> gcc compilation:

hcl-opt main.mlir --lower-to-llvm | \
    mlir-translate -mlir-to-llvmir | \
    opt -O3 -S | \
    llc -O3 -filetype=obj -o demo.o

gcc demo.o \
    -L/work/shared/users/phd/nz264/mlir/hcl-dialect/build/lib/ \
    -lhcl_runtime_utils \
    -L/work/shared/users/phd/nz264/llvm-project/build/lib/ \
    -lmlir_c_runner_utils \
    -lmlir_runner_utils \
    -o demo

Executing demo prints the correct result 0.

zzzDavid commented 1 year ago

Right now we are using a bypass to avoid this case because we are using the JIT backend in HeteroCL. See here:

https://github.com/cornell-zhang/heterocl/blob/6a3015bf1c36a919f857b525e8f9043e60c11558/python/heterocl/ast/ir_builder.py#L619-L631

zzzDavid commented 1 year ago

I will file an issue for this in the LLVM repository and post it here