Skip to content

✨ Support fixed-width classical registers across formats - #2297

Open
simon1hofmann wants to merge 9 commits into
mainfrom
codex/2289-bit-register-casts
Open

✨ Support fixed-width classical registers across formats#2297
simon1hofmann wants to merge 9 commits into
mainfrom
codex/2289-bit-register-casts

Conversation

@simon1hofmann

@simon1hofmann simon1hofmann commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖

Description

Preserve fixed-width classical-register semantics across OpenQASM and Qiskit without reconstructing bit-load graphs in each exporter.

  • Add cbit.read and cbit.write for whole-register snapshots and atomic updates. Keep cbit.cmp as the compact register-versus-constant operation for signed and unsigned predicates.
  • Represent runtime bitwise not, and, or, xor, shifts, rotations, and popcount with MLIR's fixed-width integer operations.
  • Support all six OpenQASM comparisons. Exact-width int[N] casts use signed two's-complement ordering; direct bit-register and uint[N] comparisons use unsigned ordering.
  • Import and export Qiskit Store for Clbits, indexed ClassicalRegisters, and whole ClassicalRegisters, including nested control flow.
  • Encode signed comparisons in Qiskit's unsigned expression model by XOR-biasing the sign bit. Recognize only that exact encoding on import instead of canonicalizing arbitrary Boolean graphs.
  • Validate register snapshots and reject stale or cross-region uses that a target would otherwise re-evaluate after an intervening write.
  • Share one CBit decomposition for MemRef and Adaptive QIR consumers.

Runtime shift distances must be unsigned and less than the register width. Constant overshifts fold to zero. Qiskit expressions remain limited to 64 bits. Standalone Qiskit variables remain outside the CBit register model.

jeff supports arbitrary-width cbit.cmp through per-bit array reads and Boolean logic. General cbit.read and cbit.write remain rejected because jeff has neither arbitrary-width integer casts nor logical right shift; promoting values would require incomplete logical-width emulation. QIR Base rejects the same general whole-register forms, while Adaptive QIR lowers internal values.

Fixes #2289

Validation

  • Fresh full C++ lint build after rebasing onto main.
  • 1,646 tests passed across ten affected C++ unit-test binaries.
  • uv run --no-sync pytest -q test/python/test_mlir_qiskit_translation.py: 253 tests passed.
  • uvx nox -s stubs
  • uvx nox -s lint
  • uvx nox -s cpp-lint
  • git diff --check
  • Fresh hosted CI is pending for 7bc22a446.

Codex assisted with implementation, simplification, independent review, validation, and this description under human direction.

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. (Not applicable for unreleased v4 functionality.)
  • I have added migration instructions to the upgrade guide (if needed). (Not applicable.)
  • The changes follow the project style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks. (Local validation passes; fresh hosted CI is pending.)
  • 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).
  • I have disclosed AI assistance in the PR description.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

@mergify mergify Bot added the conflict label Sep 1, 2026
@simon1hofmann
simon1hofmann force-pushed the codex/2289-bit-register-casts branch from 1823237 to d487c05 Compare September 1, 2026 16:48
@mergify mergify Bot removed the conflict label Sep 1, 2026
@simon1hofmann
simon1hofmann force-pushed the codex/2289-bit-register-casts branch from d487c05 to 8916c83 Compare September 1, 2026 18:48
@simon1hofmann
simon1hofmann marked this pull request as ready for review September 1, 2026 18:52
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 55 minutes.

@coderabbitai

coderabbitai Bot commented Sep 1, 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: Team

Run ID: e1213447-787c-425a-87ca-d495f3451026

📥 Commits

Reviewing files that changed from the base of the PR and between 717df8f and 8916c83.

📒 Files selected for processing (8)
  • docs/mlir/OpenQASM.md
  • mlir/include/mlir/Target/OpenQASM/Detail/OpenQASMParser.h
  • mlir/include/mlir/Target/OpenQASM/Frontend.h
  • mlir/lib/Dialect/QC/Translation/OpenQASMToQCEmitter.cpp
  • mlir/lib/Target/OpenQASM/OpenQASMSemantics.cpp
  • mlir/unittests/Target/OpenQASM/test_openqasm_emitter.cpp
  • mlir/unittests/Target/OpenQASM/test_openqasm_parser.cpp
  • mlir/unittests/Target/OpenQASM/test_openqasm_semantics.cpp

Included review availability: Your plan provides up to 2 included reviews per hour; 0 remain after this review.


Important

Approval pending

CodeRabbit has no unresolved comments, but it has not reviewed the latest commit.

Use the checkbox below to review the latest commit. CodeRabbit will approve the changes if it finds no blocking issues.

  • 🔍 Trigger review
📝 Summary

Summary by CodeRabbit

  • New Features

    • Added support for casting initialized bit registers to sized int[N] and uint[N] values up to 64 bits.
    • Added signed and unsigned bit-order handling, including narrow-width promotion and 64-bit values.
    • Added support for using bit-register casts in comparisons, with consistent condition reuse.
  • Bug Fixes

    • Improved validation and diagnostics for invalid cast widths, mutations, and unsupported contexts.
  • Documentation

    • Updated OpenQASM parsing and export documentation to describe supported casts and syntax limitations.

Walkthrough

The OpenQASM frontend now parses sized int and uint casts from bit registers, validates and analyzes them, emits signed or unsigned QC values, canonicalizes repeated cast conditions, and documents supported input and export syntax.

Changes

Bit-register cast support

Layer / File(s) Summary
Cast syntax and expression contract
mlir/include/mlir/Target/OpenQASM/Detail/OpenQASMParser.h, mlir/include/mlir/Target/OpenQASM/Frontend.h, mlir/unittests/Target/OpenQASM/test_openqasm_parser.cpp, docs/mlir/OpenQASM.md
The parser recognizes int and uint casts. The frontend represents bit-vector casts and signedness. Parser and input documentation cover sized casts.
Cast semantic analysis
mlir/lib/Target/OpenQASM/OpenQASMSemantics.cpp, mlir/unittests/Target/OpenQASM/test_openqasm_semantics.cpp
Semantic analysis validates widths from 1 through 64, matching bit-register sizes, initialization, and operand types. It assigns scalar types, tracks dependencies, handles promotion, and rejects invalid capture, mutation, constant, and condition uses.
QC emission and condition reuse
mlir/lib/Dialect/QC/Translation/OpenQASMToQCEmitter.cpp, mlir/unittests/Target/OpenQASM/test_openqasm_emitter.cpp, docs/mlir/OpenQASM.md
The emitter packs cast bits and applies sign or zero extension to i64. Equivalent cast comparisons share canonical conditions until classical mutation. Tests cover ordering, widths, signedness, and conditions. Export documentation describes emitted cast syntax.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: ⚪ Minimal · up to 8916c

This PR adds validated, width-bounded OpenQASM integer casts within the existing frontend and verification flow; no actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: burgholzer

Sequence Diagram(s)

sequenceDiagram
  participant OpenQASMParser
  participant OpenQASMSemantics
  participant OpenQASMToQCEmitter
  participant QCIR
  OpenQASMParser->>OpenQASMSemantics: Parse int or uint bit-register cast
  OpenQASMSemantics->>OpenQASMToQCEmitter: Lower to BitVectorCast
  OpenQASMToQCEmitter->>QCIR: Pack and extend cast value
Loading

Poem

I’m a rabbit with bits in a row
Sized casts now hop where they go
Uint shines bright
Int signs just right
And branches share carrots below

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 39 functions across 7 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #2289 by parsing sized int and uint casts, validating widths and operands, preserving bit ordering and promotion semantics, supporting cast comparisons in conditions, and add…
Out of Scope Changes check ✅ Passed The documentation, parser, frontend semantics, emitter updates, and tests are all directly related to supporting OpenQASM bit-register integer casts. No unrelated code changes are identified.
Title check ✅ Passed The title clearly identifies the main change: preserving fixed-width classical-register semantics across supported formats. It is concise and related to the documented OpenQASM and Qiskit changes.
Description check ✅ Passed The description includes a detailed summary, motivation, issue reference, implementation scope, limitations, validation results, AI disclosure, and a completed checklist. It satisfies the required tem…
Full details: Linked Issues check

Explanation

The changes satisfy issue #2289 by parsing sized int and uint casts, validating widths and operands, preserving bit ordering and promotion semantics, supporting cast comparisons in conditions, and adding targeted tests and diagnostics.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 39 functions across 7 files. (1 skipped: 1 unsupported.)

Full details: Description check

Explanation

The description includes a detailed summary, motivation, issue reference, implementation scope, limitations, validation results, AI disclosure, and a completed checklist. It satisfies the required template.


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.

@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 10 seconds.

@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@simon1hofmann
simon1hofmann force-pushed the codex/2289-bit-register-casts branch from 8916c83 to 4d5c6a1 Compare September 1, 2026 20:33
@simon1hofmann
simon1hofmann force-pushed the codex/2289-bit-register-casts branch 2 times, most recently from c5032c4 to ab336c6 Compare September 2, 2026 13:46
@simon1hofmann
simon1hofmann force-pushed the codex/2289-bit-register-casts branch from ab336c6 to fda9242 Compare September 2, 2026 14:24
@burgholzer

Copy link
Copy Markdown
Member

Also made this one a fair bit more general and hopefully usable.
I haven't checked all the details here yet, but it may still be interesting to look at already.

@mergify mergify Bot added the conflict label Sep 3, 2026
Base automatically changed from codex/openqasm-register-condition-sharing to main September 3, 2026 10:37
@burgholzer
burgholzer force-pushed the codex/2289-bit-register-casts branch from bbd9777 to fc5a2b3 Compare September 3, 2026 11:00
@burgholzer burgholzer added c++ Anything related to C++ code enhancement Improvement of existing feature MLIR Anything related to MLIR OpenQASM Anything related to OpenQASM QIR Anything related to QIR and removed conflict labels Sep 3, 2026
@burgholzer burgholzer self-assigned this Sep 3, 2026
burgholzer and others added 6 commits September 3, 2026 13:13
Use arith::CmpIPredicate across CBit, OpenQASM, Qiskit, and DD evaluation. Restrict cbit.cmp to the six unsigned predicates and reuse MLIR's evaluator where possible.

Assisted-by: Codex
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Parse sized int and uint casts from initialized bit registers and lower their little-endian representation through the existing QC bit-vector path. Preserve signedness, integer promotions, and clear width diagnostics.

Assisted-by: GPT-5.6 Sol via Codex
Signed-off-by: Simon Hofmann <simon.t.hofmann@tum.de>
Represent whole-register snapshots and writes with cbit.read and cbit.write. Reuse fixed-width integer operations for bitwise expressions across OpenQASM and Qiskit.

Preserve signed comparison semantics with sign-bit biasing. Reject exports when a target cannot preserve snapshot or type semantics.

Assisted-by: GPT-5.6 Sol via Codex
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Classify whole-register reads and writes in Adaptive QIR returned-register analysis. Reject forwarded returned writes before lowering.

Reuse the indexed OpenQASM snapshot validation and update parent tests to MLIR comparison predicates.

Assisted-by: GPT-5.6 Sol via Codex

Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Import and export bit, indexed-register, and atomic whole-register Store instructions. Preserve signed comparisons through an exact Qiskit boundary encoding.

Delete generic comparison reconstruction and share CBit decomposition between MemRef and Adaptive QIR lowering.

Assisted-by: GPT-5.6 Sol via Codex

Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
@burgholzer
burgholzer force-pushed the codex/2289-bit-register-casts branch from fc5a2b3 to 7bc22a4 Compare September 3, 2026 13:17
@burgholzer burgholzer changed the title ✨ Support runtime bit-register expressions ✨ Support fixed-width classical registers across formats Sep 3, 2026

@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.

Alright, this has become a bit of a monster. But I still think this is quite useful and expands the capabilities of the OpenQASM and Qiskit support.
Maybe you could run it through a sanity check on your side (maybe that finds a few simplifications)?
This is good to go from my side.

Comment thread mlir/lib/Conversion/QCToQIR/QIRAdaptive/QCToQIRAdaptive.cpp
Comment thread mlir/lib/Dialect/QC/Translation/OpenQASMToQCEmitter.cpp Outdated
Comment thread mlir/lib/Target/OpenQASM/OpenQASMSemantics.cpp
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

Alright, this has become a bit of a monster. But I still think this is quite useful and expands the capabilities of the OpenQASM and Qiskit support. Maybe you could run it through a sanity check on your side (maybe that finds a few simplifications)? This is good to go from my side.

I went through the changes and they look quite good to me. Also ran it through ponytail again, but that did not flag any over engineering or possible simplifications. Just three findings regarding correctness, see comments.

@burgholzer

Copy link
Copy Markdown
Member

I went through the changes and they look quite good to me. Also ran it through ponytail again, but that did not flag any over engineering or possible simplifications. Just three findings regarding correctness, see comments.

Thanks! I added a few replies. I'll hand that back to Codex, iterate once, then likely merge this. It feels ready 😌

Keep CBit for storage and use arith for exact-width integer computation.
Share zero-filling shift and integer intrinsic lowering across formats.

Extend OpenQASM and Qiskit expressions and legalize integers up to 64 bits
for jeff. Preserve wide constant comparisons and array snapshot semantics.
Reject register-valued QIR calls and fix simulator alias invalidation.

Validate with 912 Python tests, 3828 C++ tests and one QDMI skip, plus
computed-comparison regressions, documentation, stubs, and lint.

Assisted-by: Codex
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Remove redundant Qiskit expression paths, dead OpenQASM state, and private
CBit and QIR wrappers. Consolidate the classical expression design record.

Preserve measurement snapshots, exact-width integer semantics, and jeff
branch effects. Reject unsupported array snapshots and add regressions for
the confirmed translation failures.

Validate with 3,069 MLIR tests and 394 Python translation tests, plus
general lint, C++ lint, and stub regeneration.

Assisted-by: Codex
Gate Qiskit round trips on the supported adapter versions, including
explicit candidate builds. Keep simulator, OpenQASM, and jeff checks
active when minimum-dependency jobs install Qiskit 1.1.0.

Validate all 140 interchange tests with Qiskit 1.1.0 and 2.5.2, plus
general lint.

Assisted-by: Codex

@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.

Alright, I took this for another spin after your comments. I repeatedly tried to cut the complexity from this PR. However, this is as far as I got. To be fair, I think this works quite will now.
If you are happy with it as well, then let's get it in.

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 enhancement Improvement of existing feature MLIR Anything related to MLIR OpenQASM Anything related to OpenQASM QIR Anything related to QIR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ Support bit-register casts in the OpenQASM frontend

2 participants