Skip to content

✨ Add IndexSwitch operation #1925

Open
MatthiasReumann wants to merge 14 commits into
mainfrom
feat/qco-index-switch-op
Open

✨ Add IndexSwitch operation #1925
MatthiasReumann wants to merge 14 commits into
mainfrom
feat/qco-index-switch-op

Conversation

@MatthiasReumann

@MatthiasReumann MatthiasReumann commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Changes

  • ✨ Add qco.index_switch operation to TableGen.
  • ✨ Add builder functions.
  • ✨ Implement conversions.
  • ✨ Add unit tests.
  • 🐛 Allow permutations of inputs / block arguments for qco.if and qco.index_switch in IRVerification.cpp (The conversions use a first-use first-argument approach).

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:

  • Any agent that created, edited, or submitted GitHub content was explicitly authorized for that scope, as required by our AI Usage Guidelines.
  • Every agent-authored or agent-edited public text body begins with the visible disclosure 🤖 *AI text below* 🤖 (titles are exempt).
  • 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.

@MatthiasReumann MatthiasReumann added this to the MLIR Support milestone Jul 22, 2026
@MatthiasReumann MatthiasReumann self-assigned this Jul 22, 2026
@MatthiasReumann MatthiasReumann added c++ Anything related to C++ code MLIR Anything related to MLIR labels Jul 22, 2026
@MatthiasReumann

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7964295e-8c51-465d-9d9f-690622646b9b

📥 Commits

Reviewing files that changed from the base of the PR and between fdd169f and 995afda.

📒 Files selected for processing (13)
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/include/mlir/Dialect/QCO/Builder/QCOProgramBuilder.h
  • mlir/lib/Conversion/QCOToQC/QCOToQC.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/lib/Dialect/QC/Builder/QCProgramBuilder.cpp
  • mlir/lib/Dialect/QCO/IR/QCOOps.cpp
  • mlir/lib/Dialect/QCO/IR/SCF/IndexSwitchOp.cpp
  • mlir/lib/Support/IRVerification.cpp
  • mlir/unittests/Dialect/QCO/IR/test_qco_ir.cpp
  • mlir/unittests/programs/qc_programs.cpp
  • mlir/unittests/programs/qc_programs.h
  • mlir/unittests/programs/qco_programs.cpp
  • mlir/unittests/programs/qco_programs.h

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added index-based multi-way branching for quantum programs, including single-case, multi-case, and nested loop scenarios.
    • Introduced a new qco.index_switch operation with full assembly parsing/printing, verification, and target-extensions support.
    • Added new builder APIs to construct scf.index_switch/qco.index_switch for linear qubit and qtensor control flow.
  • Bug Fixes

    • Improved IR equivalence checking for switch-related qubit/tensor mappings.
  • Tests

    • Expanded IR parsing and QC↔QCO conversion coverage, plus new sample programs for switch scenarios.
  • Documentation

    • Updated the unreleased changelog references.

Walkthrough

Adds qco.index_switch, QC and QCO builder APIs, bidirectional QC↔QCO conversion support, structural-equivalence handling, and unit-test programs covering simple, multi-case, and nested-loop switches.

Changes

Index switch support

Layer / File(s) Summary
Index-switch IR contract and semantics
mlir/include/mlir/Dialect/QCO/IR/QCOOps.td, mlir/lib/Dialect/QCO/IR/*
Defines qco.index_switch, custom parsing/printing, control-flow semantics, verification, tied-value accessors, and target replacement.
Builder APIs and circuit programs
mlir/include/mlir/Dialect/{QC,QCO}/Builder/*, mlir/lib/Dialect/{QC,QCO}/Builder/*, mlir/unittests/programs/*
Adds scfIndexSwitch and qcoIndexSwitch, plus simple, multi-case, and nested-loop switch programs.
QC and QCO conversion flow
mlir/lib/Conversion/{QCToQCO,QCOToQC}/*, mlir/lib/Support/IRVerification.cpp
Adds both conversion patterns, switch-aware yield lowering, pattern registration, and value permutation handling for QCO control-flow operations.
Conversion coverage and release metadata
mlir/unittests/Conversion/*, mlir/unittests/Dialect/QCO/IR/test_qco_ir.cpp, CHANGELOG.md
Registers index-switch and nested-loop conversion tests, adds parser coverage, and updates unreleased PR references.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant QCProgramBuilder
  participant QCToQCO
  participant QCOIndexSwitchOp
  participant QCOToQC
  participant SCFIndexSwitchOp
  QCProgramBuilder->>SCFIndexSwitchOp: build index switch
  QCToQCO->>QCOIndexSwitchOp: lower switch and regions
  QCOToQC->>SCFIndexSwitchOp: recreate converted switch
Loading

Possibly related issues

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: burgholzer

Poem

A rabbit hops through cases bright,
X and Z take turns in flight.
Qubits switch, then yields align,
QC and QCO trace one line.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.27% 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 clearly and concisely summarizes the main change: adding the IndexSwitch operation.
Description check ✅ Passed The description covers the main changes and checklist; missing issue and dependency details are acceptable since they may not apply.
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.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/qco-index-switch-op

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: 14

🤖 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/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h`:
- Around line 1132-1161: Update the Doxygen comment for scfIndexSwitch to
document arg, cases, caseBodies, and defaultBody instead of the copied thenBody
and elseBody parameters. Also make the example lambdas consistently use the
builder instance shown in the invocation.

In `@mlir/include/mlir/Dialect/QCO/Builder/QCOProgramBuilder.h`:
- Line 1382: Update the parameter documentation for the affected builder method
near the `@param arg` comment to describe `arg` as the index selector/value,
accepting `std::variant<int64_t, Value>`, rather than a boolean condition. Do
not alter the method implementation or the neighboring `qcoIf` documentation.

In `@mlir/lib/Conversion/QCOToQC/QCOToQC.cpp`:
- Around line 903-905: Update the IndexSwitchOp creation in the relevant
conversion pattern to pass adaptor.getArg() instead of op.getArg(), matching the
argument access used by ConvertQCOIfOp while leaving the remaining operands and
switch configuration unchanged.

In `@mlir/lib/Conversion/QCToQCO/QCToQCO.cpp`:
- Around line 1529-1531: Remove the dead commented-out
rewriter.inlineBlockBefore line adjacent to the newBlock operations splice;
leave the active splice implementation unchanged.

In `@mlir/lib/Dialect/QC/Builder/QCProgramBuilder.cpp`:
- Around line 603-635: Update the local buildRegion callback in scfIndexSwitch
to push each newly created switch region onto regionStack before invoking its
body callback and pop it afterward, matching scfFor, scfWhile, and scfIf. Ensure
both case and default bodies execute with their active region tracked so
memrefLoad performs the correct enclosing-region and duplicate-load checks.

In `@mlir/lib/Dialect/QCO/IR/QCOOps.cpp`:
- Around line 197-265: Update the index-switch parser around the case/default
argument handling to preserve target operands: validate the first parsed args
list against result.types, resolve its regionOperands with
parser.resolveOperands, and append them to result.operands exactly once since
targets are shared. Replace both llvm::zip_equal loops with explicit arity
checks that emit parser failure before assigning argument types, while retaining
parsing for subsequent regions.

In `@mlir/lib/Dialect/QCO/IR/SCF/IndexSwitchOp.cpp`:
- Around line 156-179: Update getTiedCaseYieldedValue to validate that
bbArg.getOwner() is specifically getCaseBlock(i), not merely a block nested
under this operation, while retaining the existing operation and index checks.
Update getTiedDefaultYieldedValue to require bbArg.getOwner() ==
getDefaultBlock() before indexing the default yield targets; return nullptr for
arguments from other blocks.
- Around line 45-93: Update the unmatched-case fallback in both
IndexSwitchOp::getRegionInvocationBounds and
IndexSwitchOp::getEntrySuccessorRegions to use the default region index,
getNumRegions() - 1, instead of 0. Preserve matched-case indices and
unknown-operand behavior unchanged.

In `@mlir/lib/Support/IRVerification.cpp`:
- Around line 375-383: Update the qco::CtrlOp branch in the equivalence checker
so the failed compareValueLists condition returns false, matching the behavior
of the preceding qc::CtrlOp branch. Preserve the existing comparisons and allow
execution to continue only when both input controls and input targets are
equivalent.

In `@mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp`:
- Around line 710-712: Align the nested-loop switch fixtures so both QCO and QC
use cases {0, 1, 2} with matching branch behavior for selectors computing iv %
3. Update the NestedForLoopSwitchOp mappings in
mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp:710-712 and
mlir/unittests/Conversion/QCToQCO/test_qc_to_qco.cpp:713-715 after correcting
the fixture definitions.

In `@mlir/unittests/programs/qc_programs.cpp`:
- Around line 1984-2001: Update nestedForLoopSwitchOp so the allocated qubit
register covers every loop index used by the scfFor bound: allocate n qubits
instead of one before calling memrefLoad with iv. Preserve the existing loop
bounds, switch behavior, and measurement flow.

In `@mlir/unittests/programs/qc_programs.h`:
- Around line 918-919: Update the documentation for indexSwitchMultiCase to
state that it creates a circuit using two qubits, matching the implementation’s
size value in qc_programs.cpp.

In `@mlir/unittests/programs/qco_programs.cpp`:
- Around line 3455-3489: Update nestedForLoopSwitchOp so the allocated register
size matches the loop bound, allowing qtensorExtract to safely use every iv from
0 through n - 1. Also align qcoIndexSwitch cases with rem’s actual range {0, 1,
2}, ensuring every remainder selects an intended branch and the default remains
unreachable.

In `@mlir/unittests/programs/qco_programs.h`:
- Around line 1109-1110: Update the documentation for indexSwitchMultiCase in
QCOProgramBuilder to state that the circuit uses two qubits, matching the
implementation’s size constant.
🪄 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: 40668aa7-ef50-4fe5-a6c6-411d471799c9

📥 Commits

Reviewing files that changed from the base of the PR and between ead9fc8 and fdd169f.

📒 Files selected for processing (18)
  • CHANGELOG.md
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/include/mlir/Dialect/QCO/Builder/QCOProgramBuilder.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Conversion/QCOToQC/QCOToQC.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/lib/Dialect/QC/Builder/QCProgramBuilder.cpp
  • mlir/lib/Dialect/QCO/Builder/QCOProgramBuilder.cpp
  • mlir/lib/Dialect/QCO/IR/QCOOps.cpp
  • mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp
  • mlir/lib/Dialect/QCO/IR/SCF/IndexSwitchOp.cpp
  • mlir/lib/Support/IRVerification.cpp
  • mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp
  • mlir/unittests/Conversion/QCToQCO/test_qc_to_qco.cpp
  • mlir/unittests/programs/qc_programs.cpp
  • mlir/unittests/programs/qc_programs.h
  • mlir/unittests/programs/qco_programs.cpp
  • mlir/unittests/programs/qco_programs.h

Comment thread mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
Comment thread mlir/include/mlir/Dialect/QCO/Builder/QCOProgramBuilder.h Outdated
Comment thread mlir/lib/Conversion/QCOToQC/QCOToQC.cpp Outdated
Comment thread mlir/lib/Conversion/QCToQCO/QCToQCO.cpp Outdated
Comment thread mlir/lib/Dialect/QC/Builder/QCProgramBuilder.cpp
Comment thread mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp
Comment thread mlir/unittests/programs/qc_programs.cpp
Comment thread mlir/unittests/programs/qc_programs.h Outdated
Comment thread mlir/unittests/programs/qco_programs.cpp
Comment thread mlir/unittests/programs/qco_programs.h Outdated
@MatthiasReumann MatthiasReumann linked an issue Jul 22, 2026 that may be closed by this pull request
@MatthiasReumann

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 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.

@mergify mergify Bot added the conflict label Jul 22, 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 MLIR Anything related to MLIR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ Implement qco.index_switch operation

1 participant