cornell-zhang / hcl-dialect

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

[Op] Support multiple return values in control flow #45

Closed chhzh123 closed 2 years ago

chhzh123 commented 2 years ago

The following if program with multiple return operations cannot be directly supported by MLIR. scf.yield should be the final operation of the if scope, while std.return should be the last operation of the function, which causes contradiction and cannot pass verification. The root cause of this is the structured control flow in MLIR does not support immediate exit from all of the ancestor scope operations, so break/continue are also the cases (See discussion thread).

def foo(x):
  with hcl.if_(x > 5):
    hcl.return_(-1)
  hcl.return_(x)

(Direct translation is not valid)

module {
  func @foo(%x: i32) -> i32 {
    %five = arith.constant 5 : i32
    %cond = arith.cmpi "sgt", %x, %five : i32
    scf.if %cond {
      %cst = arith.constant -1 : i32
      std.return %cst : i32
      scf.yield // not valid
    }
    std.return %x : i32
  }
}

To mitigate the problem, one can translate the following program into a program with else branch. First yield the results as the output of scf.if operation, and return the result of scf.if, but this requires careful transformation to make it correct.

chhzh123 commented 2 years ago

https://discourse.llvm.org/t/dynamic-control-flow-break-like-operation/2495/16

chhzh123 commented 2 years ago

Currently, we just raise an error and request users to rewrite the code if break/return operations are in a deep region. Similar as #26