Skip to content

✨ Pull GPhaseOps out of multi-operation ctrl modifiers - #2013

Draft
simon1hofmann wants to merge 4 commits into
mainfrom
codex/1759-pull-gphase-from-ctrl
Draft

✨ Pull GPhaseOps out of multi-operation ctrl modifiers#2013
simon1hofmann wants to merge 4 commits into
mainfrom
codex/1759-pull-gphase-from-ctrl

Conversation

@simon1hofmann

@simon1hofmann simon1hofmann commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖

Description

Add canonicalization patterns that pull GPhaseOps out of multi-operation ctrl modifiers in the QC and QCO dialects.

A controlled global phase is materialized as:

  • a POp on the control for a single-control modifier;
  • a reduced CtrlOp applying POp to the final control for a multi-control modifier.

The existing single-operation and new multi-operation canonicalizations share the same controlled-phase construction helper. The QCO implementation also threads the updated control-qubit SSA values through the remaining modifier.

Global phases whose angle is defined inside the modifier body are conservatively left unchanged to avoid violating SSA dominance.

Fixes #1759

AI assistance was used to inspect the existing canonicalizations, implement and refactor the QC and QCO patterns, add regression tests, and run validation.

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).
  • 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.

@simon1hofmann simon1hofmann changed the title ✨ Pull s out of multi-operation modifiers ✨ Pull GPhaseOps out of multi-operation ctrl modifiers Aug 6, 2026
@simon1hofmann simon1hofmann self-assigned this Aug 6, 2026
@simon1hofmann simon1hofmann added enhancement Improvement of existing feature c++ Anything related to C++ code MLIR Anything related to MLIR labels Aug 6, 2026
@simon1hofmann simon1hofmann added this to the MLIR Support milestone Aug 6, 2026
@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved simplification of controlled operations containing global-phase gates.
    • Preserved equivalent circuit behavior when global phases appear alongside gates such as X and RXX.
    • Added support for handling multiple controlled global phases during optimization.
  • Tests

    • Added coverage for single- and multi-control circuits combining global phases with other operations.
    • Added equivalence checks against reference circuit implementations.

Walkthrough

QC and QCO now pull eligible global phases from multi-operation control modifiers and materialize equivalent controlled phase operations. New QC and QCO programs test single- and multi-control equivalence cases.

Changes

Controlled global-phase canonicalization

Layer / File(s) Summary
QC controlled-phase canonicalization
mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp, mlir/unittests/programs/qc_programs.*, mlir/unittests/Dialect/QC/IR/test_qc_ir.cpp
QC adds controlled-phase creation and extracts externally defined global phases from multi-operation control bodies. New programs and equivalence tests cover single- and multi-control cases.
QCO controlled-phase canonicalization
mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp, mlir/unittests/programs/qco_programs.*, mlir/unittests/Dialect/QCO/IR/test_qco_ir.cpp
QCO adds the same phase-lifting rewrite and nested controlled-phase construction. Tests cover global phases combined with X and RXX.
Release record
CHANGELOG.md
The Unreleased entry records PR #2013, its contributors, and its reference link.

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

Sequence Diagram(s)

sequenceDiagram
  participant CtrlOp
  participant PullGPhaseOutOfCtrl
  participant createControlledPhase
  CtrlOp->>PullGPhaseOutOfCtrl: inspect multi-operation control body
  PullGPhaseOutOfCtrl->>createControlledPhase: materialize eligible controlled phases
  createControlledPhase->>CtrlOp: insert phases and remove original global phases
Loading

Possibly related PRs

Suggested reviewers: burgholzer, denialhaag

Poem

A rabbit sees phases hop from the fold,
Through nested controls, precise and bold.
QC and QCO now agree,
With tests that verify equivalency.
PR links rest in the changelog bright.

🚥 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%. 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 summarizes the primary change: extracting GPhaseOps from multi-operation ctrl modifiers.
Description check ✅ Passed The description explains the implementation, motivation, issue, AI assistance, testing, and checklist status; no critical required section is missing.
Linked Issues check ✅ Passed The PR implements the requested QC and QCO canonicalizations, addresses SSA dominance, and adds regression tests for issue #1759.
Out of Scope Changes check ✅ Passed The implementation, tests, and changelog updates are directly related to the linked issue and stated objectives.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch codex/1759-pull-gphase-from-ctrl

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

🤖 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/Dialect/QC/IR/Modifiers/CtrlOp.cpp`:
- Around line 38-42: Remove the top-level const qualifiers from the by-value
parameters of both createControlledPhase helpers:
mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp lines 38-42 and
mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp lines 45-49. Update controlledLoc,
phaseLoc, controls, and theta to use unqualified Location, ValueRange, and Value
types while leaving behavior unchanged.
🪄 Autofix

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 Plus

Run ID: dc5bb5b1-a036-47ef-84e1-e61c0060d3f8

📥 Commits

Reviewing files that changed from the base of the PR and between 52cf1e7 and 54ae183.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/unittests/Dialect/QC/IR/test_qc_ir.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

Comment on lines +38 to +42
static void createControlledPhase(PatternRewriter& rewriter,
const Location controlledLoc,
const Location phaseLoc,
const ValueRange controls,
const Value theta) {

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.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the top-level const on by-value MLIR core types in both createControlledPhase helpers. The QCO helper mirrors the QC helper, so both signatures carry the same const Location, const ValueRange, and const Value parameters. These types are passed by value, so the qualifier gives callers no guarantee and departs from the project convention.

  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp#L38-L42: change the parameters to Location controlledLoc, Location phaseLoc, ValueRange controls, and Value theta.
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp#L45-L49: apply the same parameter change to the QCO helper.

Based on learnings: "In MLIR code under any mlir/ directory, avoid using const qualifiers on core MLIR types in function parameters/signatures (e.g., Value, Type, Attribute, Operation*, Block*, Region*, etc.)."

📍 Affects 2 files
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp#L38-L42 (this comment)
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp#L45-L49
🤖 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/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp` around lines 38 - 42, Remove the
top-level const qualifiers from the by-value parameters of both
createControlledPhase helpers: mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp lines
38-42 and mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp lines 45-49. Update
controlledLoc, phaseLoc, controls, and theta to use unqualified Location,
ValueRange, and Value types while leaving behavior unchanged.

Source: Learnings

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

Just two comments here while I have some time to kill

Comment on lines +41 to +62
/**
* @brief Materialize a global phase controlled by @p controls.
* @return The updated control qubits in their original order.
*/
static SmallVector<Value> createControlledPhase(PatternRewriter& rewriter,
const Location controlledLoc,
const Location phaseLoc,
const ValueRange controls,
const Value theta) {
assert(!controls.empty());
if (controls.size() == 1) {
return {POp::create(rewriter, controlledLoc, controls.front(), theta)
.getOutputQubit(0)};
}

auto controlledPhase = CtrlOp::create(
rewriter, controlledLoc, controls.drop_back(), controls.back(),
[&](Value target) -> Value {
return POp::create(rewriter, phaseLoc, target, theta).getOutputQubit(0);
});
return SmallVector<Value>(controlledPhase.getOutputQubits());
}

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 could potentially be optimized a little bit by splitting it into the one-control case (which could simply return a Value instead of a Vector), and the rest.
Also holds for the QC case.

Comment on lines +2218 to +2220
b.gphase(0.123);
b.x(targets[0]);
b.gphase(0.456);

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.

Slightly confused here: shouldn't these global phases be combined by the new logic and then the result would only be a single cp gate?

I suppose we do not yet support merging of gates across modifiers (such as the cp's here)..

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ Pull GPhaseOps out of multi-operation ctrl modifiers

2 participants