Skip to content

✨ Add decompose-multi-controlled pass for multi-controlled X/Z decomposition#1810

Open
simon1hofmann wants to merge 18 commits into
mainfrom
decompose-multi-controlled-gates
Open

✨ Add decompose-multi-controlled pass for multi-controlled X/Z decomposition#1810
simon1hofmann wants to merge 18 commits into
mainfrom
decompose-multi-controlled-gates

Conversation

@simon1hofmann

@simon1hofmann simon1hofmann commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Description

  • Add a decompose-multi-controlled QCO pass that decomposes multi-controlled Pauli-X and Pauli-Z gates (qco.ctrl with a single qco.x or qco.z body) into h, t, tdg, p, and cx using the Huang–Palsberg (PLDI 2024) no-ancilla algorithm (adapted from Qiskit synth_mcx_noaux_hp24).
  • MCZ uses the HP24 core directly (algebraically MCZ = H·MCX·H, with redundant Hadamard bookends canceled for k ≥ 2).
  • Expose via mqt-cc --decompose-multi-controlled and QuantumCompilerConfig::enableDecomposeMultiControlled (opt-in, default off).
  • min-controls option (default 2) keeps single-control gates (CX, CZ) intact; configurable via mqt-cc --decompose-multi-controlled-min-controls.

Usage

# Decompose CCX/CCZ and larger MCX/MCZ (default min-controls=2)
mqt-cc --decompose-multi-controlled input.mlir -o output.mlir

# Keep Toffoli/CCZ native; decompose only 3+ controls
mqt-cc --decompose-multi-controlled \
       --decompose-multi-controlled-min-controls=3 \
       input.mlir -o output.mlir

AI Assistance

Used Composer 2.5 via Cursor for parts of this change. I reviewed the full
diff and take responsibility for everything in this PR.

Checklist

  • The pull request only contains commits that are focused and relevant to this change.
  • I have added appropriate tests that cover the new/changed functionality.
  • I have updated the documentation to reflect these changes.
  • I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • I have added migration instructions to the upgrade guide (if needed).
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • I have reviewed my own code changes.

If PR contains AI-assisted content:

  • I have disclosed the use of AI tools in the PR description as per our AI Usage Guidelines.
  • AI-assisted commits include an Assisted-by: [Model Name] via [Tool Name] footer.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@simon1hofmann simon1hofmann self-assigned this Jun 24, 2026
@simon1hofmann simon1hofmann added enhancement Improvement of existing feature c++ Anything related to C++ code MLIR Anything related to MLIR labels Jun 24, 2026
@simon1hofmann simon1hofmann added this to the MLIR Support milestone Jun 24, 2026
…criptions in test_multi_controlled_decomposition.cpp to reflect the one- vs two-ancilla boundary.
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.73753% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...nsforms/Decomposition/DecomposeMultiControlled.cpp 96.8% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a configurable pass that decomposes multi-controlled X/Z qco.ctrl operations into one- and two-qubit gates, exposes it through the compiler pipeline and CLI, and expands tests and build wiring for the new behavior.

Changes

Multi-controlled gate decomposition pass

Layer / File(s) Summary
Public contracts and pass definition
mlir/include/mlir/Compiler/CompilerPipeline.h, mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/MultiControlled.h, mlir/include/mlir/Dialect/QCO/Transforms/Passes.td, CHANGELOG.md, pyproject.toml
QuantumCompilerConfig gains decomposition settings, the synthesis header declares synthesizeMcx/synthesizeMcz, TableGen defines decompose-multi-controlled, and the changelog plus typo allowlist are updated.
HP24 synthesis implementation
mlir/lib/Dialect/QCO/Transforms/Decomposition/MultiControlled.cpp
Implements the MCX and MCZ synthesis helpers, including wire tracking, dirty-ancilla routines, relative-phase construction, the HP24 core, and the public entry points.
Pass rewrite and pipeline wiring
mlir/lib/Dialect/QCO/Transforms/Decomposition/DecomposeMultiControlled.cpp, mlir/lib/Compiler/CompilerPipeline.cpp, mlir/tools/mqt-cc/mqt-cc.cpp, mlir/lib/Dialect/QCO/Transforms/CMakeLists.txt
DecomposeMultiControlled matches qualifying qco.ctrl ops, the compiler pipeline inserts it when enabled after validating min-controls, the CLI exposes the new flags, and the transforms library gets project options.
Build and test coverage
mlir/unittests/Dialect/QCO/Transforms/Decomposition/CMakeLists.txt, mlir/unittests/Compiler/test_compiler_pipeline.cpp, mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_multi_controlled_decomposition.cpp
The new decomposition test target is built, the compiler pipeline tests thread the enable flag, and the new gtests cover DD equivalence, smoke cases, edge cases, and death tests.

Sequence Diagram(s)

sequenceDiagram
  participant mqt-cc
  participant QuantumCompilerConfig
  participant QuantumCompilerPipeline as QuantumCompilerPipeline::runPipeline
  participant DecomposeMultiControlled as DecomposeMultiControlled pass
  participant synthesizeMcx
  participant synthesizeMcz

  mqt-cc->>QuantumCompilerConfig: set enableDecomposeMultiControlled and min-controls
  QuantumCompilerPipeline->>QuantumCompilerConfig: validate min-controls >= 2
  QuantumCompilerPipeline->>DecomposeMultiControlled: createDecomposeMultiControlled(options)
  DecomposeMultiControlled->>synthesizeMcx: rewrite qco.ctrl with qco.x body
  DecomposeMultiControlled->>synthesizeMcz: rewrite qco.ctrl with qco.z body
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

feature

Suggested reviewers

  • burgholzer

Poem

A bunny hopped through qubit snow,
Where X and Z learned how to split and grow.
With twinkly phases, snip-snap, neat,
The controls now dance on smaller feet.
🐇✨ Hoppy gates and tidy trails!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding a pass to decompose multi-controlled X/Z gates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description follows the template, includes summary, usage, AI disclosure, and a completed checklist, with only the optional issue footer omitted.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch decompose-multi-controlled-gates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mlir/lib/Compiler/CompilerPipeline.cpp`:
- Around line 150-154: The `runPipeline` setup in `QuantumCompilerPipeline`
should validate `config_.decomposeMultiControlledMinControls` before any stages
mutate the module, instead of relying on `qco::createDecomposeMultiControlled`
to reject bad values later. Add an upfront config check alongside the other
early validations in `runPipeline`, using the `enableDecomposeMultiControlled` /
`decomposeMultiControlledMinControls` fields, and fail fast before Stage 1 if
the value is below 2.

In `@mlir/lib/Dialect/QCO/Transforms/Decomposition/McxSynthesis.cpp`:
- Around line 461-462: Clarify the one-dirty-ancilla branch in
McxSynthesis::decompose so the condition matches the comment’s “22+ controls”
wording and the parity-sensitive logic is unambiguous. Update the check on n to
explicitly reflect the intended control-count threshold in the dirty-ancilla
selection path, and keep the branch condition aligned with the surrounding
synthesis helpers so future cleanup does not invert the rule by mistake.

In `@mlir/unittests/Compiler/test_compiler_pipeline.cpp`:
- Around line 259-265: The CompilerPipelineTest end-to-end coverage only
exercises the X-path in DecomposeMultiControlledPass, so add a second
integration case for the Z-path using mlir::qc::multipleControlledZ. Update the
test fixture in test_compiler_pipeline.cpp by following the same pattern as the
existing runPipeline call and assert the MCZ pipeline behavior through the same
QCProgramBuilder::build and CompilationRecord flow. Keep the new case alongside
the current DecomposeMultiControlledPass coverage so both multipleControlledX
and multipleControlledZ are validated through the QC→QCO→optimization pipeline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 83afc255-d120-40bc-8ed5-582fe1000e54

📥 Commits

Reviewing files that changed from the base of the PR and between 4065349 and dff6eeb.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • mlir/include/mlir/Compiler/CompilerPipeline.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/MultiControlled.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Passes.td
  • mlir/lib/Compiler/CompilerPipeline.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/DecomposeMultiControlled.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/McxSynthesis.cpp
  • mlir/tools/mqt-cc/mqt-cc.cpp
  • mlir/unittests/Compiler/test_compiler_pipeline.cpp
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/CMakeLists.txt
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_multi_controlled_decomposition.cpp
  • pyproject.toml

Comment thread mlir/lib/Compiler/CompilerPipeline.cpp
Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/McxSynthesis.cpp Outdated
Comment thread mlir/unittests/Compiler/test_compiler_pipeline.cpp Outdated
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
mlir/unittests/Compiler/test_compiler_pipeline.cpp (1)

259-281: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Disable unrelated Stage 5 passes in these decomposition checks.

Both tests treat any afterQCOCanon != afterOptimization diff as proof that multi-controlled decomposition ran, but runPipeline(..., false, false, false, true, ...) still leaves MergeSingleQubitRotationGates enabled. That means an unrelated Stage 5 change could keep these tests green even if DecomposeMultiControlled regresses.

Suggested fix
-  runPipeline(module.get(), false, false, false, true, record);
+  runPipeline(module.get(), false, true, false, true, record);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mlir/unittests/Compiler/test_compiler_pipeline.cpp` around lines 259 - 281,
The decomposition tests in CompilerPipelineTest are currently too permissive
because runPipeline still enables an unrelated Stage 5 pass, so a change in
MergeSingleQubitRotationGates could make the afterQCOCanon versus
afterOptimization comparison pass even if multi-controlled decomposition fails.
Update DecomposeMultiControlledPass and DecomposeMultiControlledPassMcz to run
with only the decomposition-relevant pipeline enabled, or otherwise disable the
Stage 5 rotation-merge path in runPipeline for these checks, so the EXPECT_NE
assertion specifically validates DecomposeMultiControlled and the
multipleControlledX/multipleControlledZ cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mlir/unittests/Compiler/test_compiler_pipeline.cpp`:
- Around line 283-297: The test currently only checks that
QuantumCompilerPipeline::runPipeline fails, which still allows the rejection to
happen later in DecomposeMultiControlled after earlier stages have run. Update
CompilerPipelineTest.RejectsDecomposeMultiControlledMinControlsBelowTwo to also
assert that CompilationRecord::afterQCImport remains empty when
decomposeMultiControlledMinControls is below two, so the preflight validation is
enforced before Stage 1 or any intermediate records are produced.

In
`@mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_multi_controlled_decomposition.cpp`:
- Around line 378-404: The two “untouched” tests only verify that one
multi-controlled op remains, so they can miss regressions where the surviving
operation changes kind; update McxDecompositionTest::LeavesMultiOpCtrlUntouched
and McxDecompositionTest::LeavesMultiControlledHUntouched to assert the
preserved op is still the expected CtrlOp/MCH form and that its body is
unchanged after runDecomposePass, using the existing QCOProgramBuilder setup and
countMultiControlledOps as a secondary check only.

---

Outside diff comments:
In `@mlir/unittests/Compiler/test_compiler_pipeline.cpp`:
- Around line 259-281: The decomposition tests in CompilerPipelineTest are
currently too permissive because runPipeline still enables an unrelated Stage 5
pass, so a change in MergeSingleQubitRotationGates could make the afterQCOCanon
versus afterOptimization comparison pass even if multi-controlled decomposition
fails. Update DecomposeMultiControlledPass and DecomposeMultiControlledPassMcz
to run with only the decomposition-relevant pipeline enabled, or otherwise
disable the Stage 5 rotation-merge path in runPipeline for these checks, so the
EXPECT_NE assertion specifically validates DecomposeMultiControlled and the
multipleControlledX/multipleControlledZ cases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f9c18476-abd2-4d99-94d9-f4385100f19b

📥 Commits

Reviewing files that changed from the base of the PR and between dff6eeb and b2f30eb.

📒 Files selected for processing (5)
  • mlir/lib/Compiler/CompilerPipeline.cpp
  • mlir/lib/Dialect/QCO/Transforms/CMakeLists.txt
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/MultiControlled.cpp
  • mlir/unittests/Compiler/test_compiler_pipeline.cpp
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_multi_controlled_decomposition.cpp

Comment thread mlir/unittests/Compiler/test_compiler_pipeline.cpp
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@simon1hofmann simon1hofmann requested a review from burgholzer June 24, 2026 20:56
@mergify mergify Bot added the conflict label Jun 24, 2026
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>
@mergify mergify Bot added conflict and removed conflict labels Jun 25, 2026
@mergify mergify Bot added conflict and removed conflict labels Jun 30, 2026
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>
@mergify mergify Bot removed the conflict label Jul 5, 2026
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>

@burgholzer burgholzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally found some time to go through this.
Really cool to see this implemented and have it as part of our compiler collection!

I have a couple of comments here that are more questions on the general design. The actual implementation seems to be fine as confirmed by the tests.

I really like these kinds of tests because this also means that we can heavily rely on agentic AI to actually improve the implementation efficiency as long as the output is still correct 🙌

Comment thread mlir/include/mlir/Compiler/CompilerPipeline.h
Comment thread mlir/lib/Compiler/CompilerPipeline.cpp
Comment on lines +122 to +123
[[nodiscard]] static qc::QuantumComputation
funcOpToQuantumComputation(func::FuncOp funcOp, std::size_t& numQubits) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I generally really like the verification via the DD package. As such, this kind of translation is necessary at the moment.
I see at least two potential directions for follow-ups here:

  • make this a more general feature that we can convert programs to quantum computations. Might require too much work for too little benefit.
  • generalize the DD package so that it can also work with the MLIR code base. While it might not be completely possible to detangle the DD package from the old IR module, a large part of the functionality is actually independent. We could potentially port the simulate and buildFunctionality functions over to MLIR programs with only moderate effort. That would avoid going through the QuantumComputation class for tests and computations like these.

Comment on lines +207 to +208
EXPECT_TRUE(dd->multiply(decomposedDD, dd->conjugateTranspose(referenceDD))
.isIdentity(/*upToGlobalPhase=*/false));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that numerical accuracy is a problem here so that. Simple comparison of the resulting DDs (EXPECT_EQ) is not sufficient here and fails, right?

@simon1hofmann simon1hofmann Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EXPECT_EQ checks structural equivalence right? In our case, we compare the decomposed mcx/mcz (decomposedDD) with an undecomposed reference mcx/mcz (referenceDD).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but since DDs are canonical, the respective pointers and weights should actually be equivalent (in the literal sense).
In many practical cases, this doesn't hold because of numerical inaccuracies that get in the way. Then, something like the computation that is in the code at the moment is necessary.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might once more just be me, but is there really any value in having a dedicated header file for these functions? Couldn't these simply be part of the respective pass CPP file?
It feels like these are very particular function that do not have any public API usage or at least none that I could foresee.
Would you agree?

Edit: having gone through more of the PR, I think I just don't quite like the idea that so much of the pass logic is actively decoupled from MLIR. For the most part, we have the MLIR pass logic and that then builds some auxiliary data structures, which are passed to a collection of methods that doesn't even really care about MLIR.
I would have thought/hoped that we could integrate the respective functionality a little tighter with MLIR itself and avoid auxiliary boilerplate as much as possible.
However, I can also see that the current design also has its pro's; decoupling the infrastructure from the actual pass logic.
Maybe this is just me leaning towards the tightly integrated solution.
Tagging @munich-quantum-toolkit/mqt-cc here for visibility. Maybe someone has a comment or a different perspective

Comment on lines +137 to +169
void c3x() {
h(3);
p(0, K_PI8);
p(1, K_PI8);
p(2, K_PI8);
p(3, K_PI8);
cx(0, 1);
p(1, -K_PI8);
cx(0, 1);
cx(1, 2);
p(2, -K_PI8);
cx(0, 2);
p(2, K_PI8);
cx(1, 2);
p(2, -K_PI8);
cx(0, 2);
cx(2, 3);
p(3, -K_PI8);
cx(1, 3);
p(3, K_PI8);
cx(2, 3);
p(3, -K_PI8);
cx(0, 3);
p(3, K_PI8);
cx(2, 3);
p(3, -K_PI8);
cx(1, 3);
p(3, K_PI8);
cx(2, 3);
p(3, -K_PI8);
cx(0, 3);
h(3);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a fixed decomposition for a three-controlled X gate, right?
Maybe this also fits well with the other suggestion of making this an explicit special case of the pattern instead of hard-coding it here.

Comment on lines +171 to +188
private:
[[nodiscard]] std::size_t wireIndex(std::size_t local) const {
return remap_.empty() ? local : remap_[local];
}

[[nodiscard]] Value wire(std::size_t local) const {
return (*wires_)[wireIndex(local)];
}

void setWire(std::size_t local, Value value) {
(*wires_)[wireIndex(local)] = value;
}

OpBuilder* builder_;
Location loc_;
SmallVector<Value>* wires_;
ArrayRef<std::size_t> remap_;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These feel like generally useful helpers. Is there any good place we could put these? Are there other places where this could turn out to become useful (synthesis for example)?

It's totally fine to keep this here for now. I'd just like to avoid a situation where every pass invents its own helper routines.

Edit: this kind of feels like our program builder to some degree. Could it be generalized so that it is also genuinely useful here?

Comment on lines +203 to +210
static void addResetGadget(GateEmitter& builder, std::size_t q0, std::size_t q1,
std::size_t q2) {
builder.cx(q1, q2);
builder.t(q2);
builder.cx(q0, q2);
builder.tdg(q2);
builder.h(q2);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to model this as inv(action)? Now that we allow multiple unitaries in a modifier, this feels like quite a natural way to express this.

const std::size_t controlsEnd = numControls;

SmallVector<std::size_t, 16> map;
const auto relativeStep = [&](const double sign, const std::size_t begin,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of feels wrong that sign is not a bool here.

gate of the target).
}];
let options = [Option<
"minControls", "min-controls", "uint64_t", "2",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC tablegen also allows to directly place constraints on options/parameters. Maybe it is worth looking into whether this would simplify some of the error handling code throughout this PR.

@mergify mergify Bot added the conflict label Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Anything related to C++ code conflict enhancement Improvement of existing feature MLIR Anything related to MLIR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants