🐛 Fix CtrlOp::getBodyUnitary() for operations with parameters#1464
🐛 Fix CtrlOp::getBodyUnitary() for operations with parameters#1464denialhaag merged 9 commits intomainfrom
Conversation
📝 WalkthroughSummary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughThe pull request updates parameter handling in QC and QCO program builders to use a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
burgholzer
left a comment
There was a problem hiding this comment.
I am not 100% that this is the right solution here.
The IR for parasitized operations shouldn't actually pass verification because the verifier of the QC) CtrlOp asserts that any CtrlOp only contains two operations (the UnitaryOp and the yield). I am surprised that we are not hitting this so far.
I assume that we should be running mlir::verify in the compiler pipeline tests on all circuits constructed by any builders or produced by the compiler.
I would argue that the real fix here is to modify the builders so that they directly insert the constant operations in the highest scope possible.
This might prevent us from ever declaring the CtrlOp as IsolatedFromAbove, which might not be feasible anyway because it was (and needs to be) valid to use a parameter in a controlled rotation gate that was defined outside of the region.
My request here would be two-fold
- Can we fix the builders instead of iterating over the control op body?
- Can we ensure that the IR in our tests is verified (especially in the compiler pipeline tests)?
What's the argument against just moving the parameter into the body? Wouldn't that also simplify optimizations involving the control modifier since it actually is
Do you have an idea how we could define this "highest scope possible"? Because wouldn't that be the
I guess that should be possible, but how do we want to handle that in actual non-test code? Running a verification after every optimization would probably cause a lot of unnecessary overhead. Or do we just assume that the optimizations are all doing valid transformations? Because it could also happen that "optimization 1" will cause an invalid IR which "optimization 2" will transform back into a valid IR but with a different functionality than intended and thus only the final IR check might be insufficient? |
There might be multiple uses of the same parameter across operations and we do not want to bury these in (potentially nested) modifier regions.
The canonicalization pipeline that we employ as part of the compiler pipeline already employs this "bubbling up as high as possible". You can see that in the various stages of the IR in the tests. This should also give you an indication of where the appropriate place for the constant ops is. I believe it should be the first regions with with IsolatedFromAbove trait (which might be the
See https://mlir.llvm.org/getting_started/DeveloperGuide/#ir-should-be-valid-before-and-after-each-pass and https://mlir.llvm.org/getting_started/DeveloperGuide/#ir-verifier |
Thanks for the links! I need to do some reading and experimenting, but there definitely is something broken here because Edit: I also made sure that the test case I added will fail without my proposed fix, that is why I'm sure it currently is broken Edit Nr. 2: Ah, I think I got what you're saying - in the actual code it's not an issue but just the test code because it's running without the verifier at the moment. I'll check out adding the verifier to the broken test case |
|
What would be good is to reduce this PR to a reproducer of the issues you are seeing so that we have them as logs in the CI. We are currently not seeing them in the compiler pipeline tests, but this could very much be due to us not having a test with controlled rotations (which we should add on that case). |
cc9488f to
5fae654
Compare
Thanks.
Yeah. Seams like a bug in the builder to me. Or in our definition of a valid control modifier, but I am heavily leaning to the bug. @denialhaag could you maybe briefly take a look at this? |
I am all but certain that the issue is that we are not resolving the core/mlir/lib/Dialect/QC/Builder/QCProgramBuilder.cpp Lines 227 to 234 in 0089f7d Instead, the core/mlir/lib/Dialect/QC/IR/Operations/StandardGates/RXOp.cpp Lines 22 to 26 in 0089f7d I think we could simply call the |
Indeed, that seems to be the main issue and a nice solution to the issue! Thanks for quickly getting back to this. |
burgholzer
left a comment
There was a problem hiding this comment.
This looks good now. Thanks @denialhaag 🙏
The last commit should be reverted though as it will trigger warnings in the IDE again.
These are the parameter names of the underlying methods. The "ods" is part of that. If removed, the linter complains that the definition uses different names from the declaration
This reverts commit 9d697e9.
Done!
Thanks for the explanation; I did not know that! |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@CHANGELOG.md`:
- Line 14: PR `#1464` is a bug fix grouped under the "Added" section in
CHANGELOG.md; please add a separate "Fixed" entry referencing [`#1464`] (and
mentioning CtrlOp::getBodyUnitary()) or move a concise note about the bug fix
out of the "Added" section into a new "Fixed" subsection so the fix is
discoverable while keeping the infrastructure grouping for the other MLIR PRs.
## Description This PR fixes the argument names of the build method of most operations, after I had eroneously simplified them. This will silence warnings in IDEs (see #1464 (review)). ## Checklist: - [x] The pull request only contains commits that are focused and relevant to this change. - [x] ~I have added appropriate tests that cover the new/changed functionality.~ - [x] ~I have updated the documentation to reflect these changes.~ - [x] ~I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.~ - [x] ~I have added migration instructions to the upgrade guide (if needed).~ - [x] The changes follow the project's style guidelines and introduce no new warnings. - [x] The changes are fully tested and pass the CI checks. - [x] I have reviewed my own code changes.


Description
While debugging test cases in #1426, I finally figured out why
CtrlOp::getBodyUnitary()sometimes returned an invalidUnitaryOpInterface.Whenever an operation has at least one parameter, the first operation in the modifier's body will be a
arith.constantand not the unitary operation like it is currently assumed in the function.This PR resolves this by iterating over all operations in the body and only returning when the first
UnitaryOpInterfaceoperation has been found or there is none.It affects all
crx,crzz,cu, ... operations.Required for #1426
Checklist: