[FIRRTLFolds] Fold binary operators with one zero-width operand
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 524
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Description
Test case, produced while working on #4395 :
firrtl.circuit "zeroWidthOperand" {
firrtl.module @zeroWidthOperand(
in %in0 : !firrtl.uint<0>,
in %in1 : !firrtl.uint<1>,
out %o_add1: !firrtl.uint<2>,
out %o_add2: !firrtl.uint<2>,
out %o_sub1: !firrtl.uint<2>,
out %o_sub2: !firrtl.uint<2>,
out %o_mul1: !firrtl.uint<1>,
out %o_mul2: !firrtl.uint<1>,
out %o_div1: !firrtl.uint<0>,
out %o_div2: !firrtl.uint<1>,
out %o_rem1: !firrtl.uint<0>,
out %o_rem2: !firrtl.uint<0>,
out %o_dshl1: !firrtl.uint<1>,
out %o_dshl2: !firrtl.uint<1>,
out %o_dshlw1: !firrtl.uint<0>,
out %o_dshlw2: !firrtl.uint<1>,
out %o_dshr1: !firrtl.uint<0>,
out %o_dshr2: !firrtl.uint<1>,
out %o_and1: !firrtl.uint<1>,
out %o_and2: !firrtl.uint<1>,
out %o_or1: !firrtl.uint<1>,
out %o_or2: !firrtl.uint<1>,
out %o_xor1: !firrtl.uint<1>,
out %o_xor2: !firrtl.uint<1>
) {
%add1 = firrtl.add %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<2>
%add2 = firrtl.add %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<2>
%sub1 = firrtl.sub %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<2>
%sub2 = firrtl.sub %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<2>
%mul1 = firrtl.mul %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%mul2 = firrtl.mul %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%div1 = firrtl.div %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%div2 = firrtl.div %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%rem1 = firrtl.rem %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%rem2 = firrtl.rem %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<0>
%dshl1 = firrtl.dshl %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%dshl2 = firrtl.dshl %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%dshlw1 = firrtl.dshlw %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%dshlw2 = firrtl.dshlw %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%dshr1 = firrtl.dshr %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%dshr2 = firrtl.dshr %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%and1 = firrtl.and %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%and2 = firrtl.and %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%or1 = firrtl.or %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%or2 = firrtl.or %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%xor1 = firrtl.xor %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%xor2 = firrtl.xor %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
firrtl.strictconnect %o_add1, %add1 : !firrtl.uint<2>
firrtl.strictconnect %o_add2, %add2 : !firrtl.uint<2>
firrtl.strictconnect %o_sub1, %sub1: !firrtl.uint<2>
firrtl.strictconnect %o_sub2, %sub2: !firrtl.uint<2>
firrtl.strictconnect %o_mul1, %mul1: !firrtl.uint<1>
firrtl.strictconnect %o_mul2, %mul2: !firrtl.uint<1>
firrtl.strictconnect %o_div1, %div1 : !firrtl.uint<0>
firrtl.strictconnect %o_div2, %div2 : !firrtl.uint<1>
firrtl.strictconnect %o_rem1, %rem1 : !firrtl.uint<0>
firrtl.strictconnect %o_rem2, %rem2 : !firrtl.uint<0>
firrtl.strictconnect %o_dshl1, %dshl1 : !firrtl.uint<1>
firrtl.strictconnect %o_dshl2, %dshl2 : !firrtl.uint<1>
firrtl.strictconnect %o_dshlw1, %dshlw1 : !firrtl.uint<0>
firrtl.strictconnect %o_dshlw2, %dshlw2 : !firrtl.uint<1>
firrtl.strictconnect %o_dshr1, %dshr1 : !firrtl.uint<0>
firrtl.strictconnect %o_dshr2, %dshr2 : !firrtl.uint<1>
firrtl.strictconnect %o_and1, %and1 : !firrtl.uint<1>
firrtl.strictconnect %o_and2, %and2 : !firrtl.uint<1>
firrtl.strictconnect %o_or1, %or1 : !firrtl.uint<1>
firrtl.strictconnect %o_or2, %or2 : !firrtl.uint<1>
firrtl.strictconnect %o_xor1, %xor1 : !firrtl.uint<1>
firrtl.strictconnect %o_xor2, %xor2 : !firrtl.uint<1>
}
}
With that PR, the operations with zero-width return are replaced with zero but the others are not folded/canonicalized (and at least most of them can be).
Here's the current firtool -ir-fir output on the above:
module {
firrtl.circuit "zeroWidthOperand" {
firrtl.module @zeroWidthOperand(in %in0: !firrtl.uint<0>, in %in1: !firrtl.uint<1>, out %o_add1: !firrtl.uint<2>, out %o_add2: !firrtl.uint<2>, out %o_sub1: !firrtl.uint<2>, out %o_sub2: !firrtl.uint<2>, out %o_mul1: !firrtl.uint<1>, out %o_mul2: !firrtl.uint<1>, out %o_div1: !firrtl.uint<0>, out %o_div2: !firrtl.uint<1>, out %o_rem1: !firrtl.uint<0>, out %o_rem2: !firrtl.uint<0>, out %o_dshl1: !firrtl.uint<1>, out %o_dshl2: !firrtl.uint<1>, out %o_dshlw1: !firrtl.uint<0>, out %o_dshlw2: !firrtl.uint<1>, out %o_dshr1: !firrtl.uint<0>, out %o_dshr2: !firrtl.uint<1>, out %o_and1: !firrtl.uint<1>, out %o_and2: !firrtl.uint<1>, out %o_or1: !firrtl.uint<1>, out %o_or2: !firrtl.uint<1>, out %o_xor1: !firrtl.uint<1>, out %o_xor2: !firrtl.uint<1>) {
%0 = firrtl.add %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<2>
%1 = firrtl.sub %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<2>
%2 = firrtl.sub %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<2>
%3 = firrtl.mul %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%4 = firrtl.div %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%5 = firrtl.div %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%6 = firrtl.rem %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%7 = firrtl.rem %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<0>
%8 = firrtl.dshl %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%9 = firrtl.dshl %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%10 = firrtl.dshlw %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%11 = firrtl.dshlw %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%12 = firrtl.dshr %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<0>
%13 = firrtl.dshr %in1, %in0 : (!firrtl.uint<1>, !firrtl.uint<0>) -> !firrtl.uint<1>
%14 = firrtl.and %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%15 = firrtl.or %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
%16 = firrtl.xor %in0, %in1 : (!firrtl.uint<0>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.strictconnect %o_add1, %0 : !firrtl.uint<2>
firrtl.strictconnect %o_add2, %0 : !firrtl.uint<2>
firrtl.strictconnect %o_sub1, %1 : !firrtl.uint<2>
firrtl.strictconnect %o_sub2, %2 : !firrtl.uint<2>
firrtl.strictconnect %o_mul1, %3 : !firrtl.uint<1>
firrtl.strictconnect %o_mul2, %3 : !firrtl.uint<1>
firrtl.strictconnect %o_div1, %4 : !firrtl.uint<0>
firrtl.strictconnect %o_div2, %5 : !firrtl.uint<1>
firrtl.strictconnect %o_rem1, %6 : !firrtl.uint<0>
firrtl.strictconnect %o_rem2, %7 : !firrtl.uint<0>
firrtl.strictconnect %o_dshl1, %8 : !firrtl.uint<1>
firrtl.strictconnect %o_dshl2, %9 : !firrtl.uint<1>
firrtl.strictconnect %o_dshlw1, %10 : !firrtl.uint<0>
firrtl.strictconnect %o_dshlw2, %11 : !firrtl.uint<1>
firrtl.strictconnect %o_dshr1, %12 : !firrtl.uint<0>
firrtl.strictconnect %o_dshr2, %13 : !firrtl.uint<1>
firrtl.strictconnect %o_and1, %14 : !firrtl.uint<1>
firrtl.strictconnect %o_and2, %14 : !firrtl.uint<1>
firrtl.strictconnect %o_or1, %15 : !firrtl.uint<1>
firrtl.strictconnect %o_or2, %15 : !firrtl.uint<1>
firrtl.strictconnect %o_xor1, %16 : !firrtl.uint<1>
firrtl.strictconnect %o_xor2, %16 : !firrtl.uint<1>
}
}
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the FIRRTLFolds pass and use firtool -ir-fir on the supplied zeroWidthOperand MLIR case to inspect the current folding behavior. Extend folding or canonicalization for the listed binary operators with one zero-width operand, then verify that the expected operations are folded in the output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100