[DC] Connecting up DC during incremental lowering
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 524
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Description
I'm working on lowering to DC and I'd like to make a set of passes which do so incrementally rather than having to do it monolithically in one shot.
A real example:
```mlir
// Original code
ibis.class @C {
ibis.method @math(%a: i32, %b: i32) -> i32 {
%1 = comb.add bin %a, %b : i32
ibis.return %1 : i32
}
}
ibis.class @User {
ibis.instance @c, @C
ibis.method @wrapper(%a: i32, %b: i32) -> i32 {
%x = ibis.call @c::@math(%a, %b): (i32, i32) -> i32
ibis.return %x : i32
}
}
```
The `ibis-call-pass` as a first step converts the arguments into a single struct:
```mlir
ibis.class @C {
ibis.method @math(%arg: !hw.struct) -> i32 {
%a, %b = hw.struct_explode %arg : !hw.struct
%0 = comb.add bin %a, %b : i32
ibis.return %0 : i32
}
}
ibis.class @User {
ibis.instance @c, @C
ibis.method @wrapper(%arg: !hw.struct) -> i32 {
%a, %b = hw.struct_explode %arg : !hw.struct
%0 = hw.struct_create (%a, %b) : !hw.struct
%1 = ibis.call @c::@math(%0) : (!hw.struct) -> i32
ibis.return %1 : i32
}
}
```
Notice that it only affects the method boundaries -- doesn't touch or analyze the `comb.add`.
The next step is to DC-ify the calls/methods, meaning wrap the method arguments with `dc.value`s. Ideally, I would like to do this incrementally like I do with the last step -- changing the method signatures and add `dc.pack`/`dc.unpack`, so we don't have to monolithically convert all the control flow over to DC. Those two operations, however, consume/produce a `token`. Wiring the tokens together is not necessarily the right thing to do -- the control flow may dictate something different. Also, where do I get the `token` for the call's `pack`/`unpack`?
To demonstrate:
```mlir
// class C omitted
ibis.class @User {
ibis.instance @c, @C
ibis.method @wrapper(%arg: !dc.value>) -> !dc.value {
// Unwrap the args.
%inputToken, %unwrapped = dc.unpack %arg : !dc.value>
// What should I do with %inputToken?
%a, %b = hw.struct_explode %unwrapped : !hw.struct
// Wrap for the method call.
%0 = hw.struct_create (%a, %b) : !hw.struct
%tokenForCall = ... // Where should I get this?
%valueForCall = dc.pack %tokenForCall, %0 : !hw.struct
%1 = ibis.call @c::@math(%0) : (!dc.value>) -> !dc.value
// Unpack the result.
%callReturnToken, %retData = dc.unpack %1 : !dc.value
// What should I do with %callReturnToken?
// Pack the result.
%methodReturnToken = ... // where should I get this Value?
%ret = dc.pack %methodReturnToken, %retData : i32
ibis.return %ret : !dc.value
}
}
```
Suggestions? Perhaps the answer is to do all the control flow to DC in one pass. I'd rather not do that since it requires that one pass have knowledge of all the control flow constructs (and we're planning to add some custom control flow to ibis) so it's not just CF.
I'll post my suggested options as comments below so as to not frame the discussion as a selection between my options.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.