Skip to content

[FIRRTL] Add mux2cell/mux4cell canonicalization patterns#10414

Open
anaumchev wants to merge 7 commits into
llvm:mainfrom
anaumchev:muxcell-canonicalization
Open

[FIRRTL] Add mux2cell/mux4cell canonicalization patterns#10414
anaumchev wants to merge 7 commits into
llvm:mainfrom
anaumchev:muxcell-canonicalization

Conversation

@anaumchev
Copy link
Copy Markdown

@anaumchev anaumchev commented May 8, 2026

Summary

This PR implements two FIRRTL improvements:

  1. Issue [FIRRTL] Implement folder/canonicalizer for muxcell intrinsics #5448: Folder/canonicalization patterns for muxcell2 and muxcell4 intrinsics
  2. Issue [FIRRTL] Expand Whens Doesn't Check firrtl.wire initialization of domain type #10248: Check that domain wires are driven before their subfields can be accessed

Changes

Issue #5448 - muxcell Canonicalization

lib/Dialect/FIRRTL/FIRRTLFolds.cpp

Added Mux4CellIntrinsicOp::fold() with constant folding optimizations:

  • mux4(sel, x, x, x, x) to x
  • mux4(0/1/2/3, a, b, c, d) to a/b/c/d
  • mux4(sel, c, c, c, c) to c
  • mux4(sel, 1, 0, 1, 0) to sel (identity)

lib/Dialect/FIRRTL/FIRRTLCanonicalization.td

Added TableGen rewrite patterns:

  • Mux2Not: mux2cell(cond, 0, 1) to not(cond)
  • Mux4Not: mux4cell(cond, 0, 1, 0, 1) to not(cond)

Issue #10248 - Undriven Domain Wire Check

lib/Dialect/FIRRTL/Transforms/InferDomains.cpp

Added check that domain wires are driven before their subfields can be accessed. This catches the error early in InferDomains instead of later in LowerClasses.

Tests

  • muxcell-canonicalization.mlir (NEW): Regression test for muxcell patterns
  • canonicalization.mlir: Extended with 12 integration test cases
  • infer-domains-infer-errors.mlir: Extended with test for undriven domain wire error

All existing FIRRTL tests pass.

Fixes

Fixes #5448
Fixes #10248

Implement folder and canonicalization patterns for muxcell intrinsics
(int.muxcell2 and int.muxcell4) as requested in issue llvm#5448.

Changes:
- Mux4CellIntrinsicOp::fold(): Added constant folding for:
  - UInt<0> -> 0
  - mux4(sel, x, x, x, x) -> x
  - mux4(0/1/2/3, a, b, c, d) -> a/b/c/d
  - mux4(sel, c, c, c, c) -> c
  - mux4(sel, 1, 0, 1, 0) -> sel (identity)

- Mux2Not/Mux4Not patterns: Canonicalize mux(sel, 0, 1) to not(sel)

Added tests:
- muxcell-canonicalization.mlir: Standalone regression test
- canonicalization.mlir: Integration tests for all patterns

Fixes llvm#5448
anaumchev added 2 commits May 8, 2026 15:25
Use ternary operator for cleaner code in Mux4CellIntrinsicOp::fold()
constant selector case.
Add a check in the InferDomains pass to verify that domain wires are
driven before their subfields can be accessed. This catches the issue
early in InferDomains instead of later in LowerClasses, as requested
in issue llvm#10248.

Previously, accessing a subfield of an undriven domain wire would not
produce an error until LowerClasses, which was confusing. Now it
produces a clear error message: 'accesses an undriven domain; domain
wires must be driven before their subfields can be accessed'
anaumchev added 4 commits May 12, 2026 12:40
- Update TableGen pattern comments to say 'not(cond)' instead of '~cond'
- Add clarifying comment about type constraint for identity pattern
- Add newline at EOF for muxcell-canonicalization.mlir
This makes the variable name more descriptive, indicating
that it holds the folded (adaptor) values for the mux operands.
The identity pattern 'mux4cell(sel, 1, 0, 1, 0) -> sel' was mathematically
incorrect. According to mux4cell semantics:
  - sel=0 -> v0=1
  - sel=1 -> v1=0

For uint<1> selector, this means both cases return not(sel), not sel!

Fix:
- Remove buggy fold that returned getSel()
- Add Mux4SelNot TableGen pattern for mux4cell(sel, 1, 0, 1, 0) -> not(sel)
- Register pattern in getCanonicalizationPatterns
- Update tests to expect not(sel)

Fixes bug discovered by oracle analysis.
Explains why the check is needed: DomainSubfieldOp has a DomainType
input which is not processed by unifyAssociations.
@seldridge
Copy link
Copy Markdown
Member

The PR and commit text looks like it may have been created with the assistance of other tools. Can you provide more information on to what extent AI tooling was used in the creation of this work, if at all? See: https://github.com/llvm/circt/blob/main/docs/AIToolPolicy.md

Apologies if no AI was involved here.

Also, it would be better to keep this PR separate from a second, proposed PR, that handles the issue with domains. However, looking at the change here, I don't think this is quite right as the ExpandWhens pass is usually where all initialization checking is done. After that pass, everything can assume that things are driven, and driven exactly once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIRRTL] Expand Whens Doesn't Check firrtl.wire initialization of domain type [FIRRTL] Implement folder/canonicalizer for muxcell intrinsics

2 participants