[core] Don't let DQE eliminate an entry point's last allocation - #5135
Closed
mitchdz wants to merge 1 commit into
Closed
[core] Don't let DQE eliminate an entry point's last allocation#5135mitchdz wants to merge 1 commit into
mitchdz wants to merge 1 commit into
Conversation
A kernel that allocates qubits but applies no operation to them loses its
register entirely. sample() returns no counts at all and get_state()
segfaults dereferencing a null SimulationState:
@cudaq.kernel
def allocate_only(n: int):
q = cudaq.qvector(n)
cudaq.sample(allocate_only, 3) # {} instead of { 000:1000 }
cudaq.get_state(allocate_only, 3) # SIGSEGV
DQE erases an alloca whose only use is a dealloc, and a null_wire whose
only use is a sink. That is sound when nothing observes the register, but
an entry point's register is observable: sample() implicitly measures every
allocated qubit and get_state() returns the whole register. Since NVIDIA#4993
enabled value semantics for local simulators as well, such a kernel now
reaches the runtime with no qubits at all.
Keep the allocation when it is the last one in a cudaq-entrypoint function.
Partially used registers are unaffected, and dead qubits in non-entry-point
functions are still eliminated.
Adds a FileCheck test for both halves of that rule and an execution test
asserting the observable contract. Both fail without the fix.
Signed-off-by: mdzurick <mitch_dz@hotmail.com>
CI Summary (
|
| Job | Result | Link |
|---|---|---|
build_and_test |
❌ failure | view |
Top-level jobs (13)
| Job | Result |
|---|---|
binaries |
⏩ skipped |
build_and_test |
❌ failure |
config_devdeps |
✅ success |
config_source_build |
⏩ skipped |
config_wheeldeps |
✅ success |
devdeps |
✅ success |
docker_image |
⏩ skipped |
gen_code_coverage |
⏩ skipped |
metadata |
✅ success |
python_metapackages |
⏩ skipped |
python_wheels |
⏩ skipped |
source_build |
⏩ skipped |
wheeldeps |
✅ success |
⏩ Skipped jobs (7) — intentionally skipped on PR builds; run on merge_group / workflow_dispatch
| Job |
|---|
binaries |
config_source_build |
docker_image |
gen_code_coverage |
python_metapackages |
python_wheels |
source_build |
All sub-jobs (42) — every matrix leg, with links
| Job | Status | Link |
|---|---|---|
| Build and test (amd64, gcc12, openmpi) / Dev environment (Debug) | ❌ failure | view |
| Build and test (amd64, gcc12, openmpi) / Dev environment (Python) | ❌ failure | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Debug) | ❌ failure | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Python) | ❌ failure | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Debug) | ❌ failure | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Python) | ❌ failure | view |
| CI Summary | ❔ in_progress | view |
| Configure build (devdeps) | ✅ success | view |
| Configure build (source_build) | ⏩ skipped | view |
| Configure build (wheeldeps) | ✅ success | view |
| Create CUDA Quantum installer | ⏩ skipped | view |
| Create Docker images | ⏩ skipped | view |
| Create Python metapackages | ⏩ skipped | view |
| Create Python wheels | ⏩ skipped | view |
| Gen code coverage | ⏩ skipped | view |
| Load dependencies (amd64, gcc12) / Caching | ✅ success | view |
| Load dependencies (amd64, gcc12) / Finalize | ✅ success | view |
| Load dependencies (amd64, gcc12) / Metadata | ✅ success | view |
| Load dependencies (amd64, llvm) / Caching | ✅ success | view |
| Load dependencies (amd64, llvm) / Finalize | ✅ success | view |
| Load dependencies (amd64, llvm) / Metadata | ✅ success | view |
| Load dependencies (arm64, gcc12) / Caching | ✅ success | view |
| Load dependencies (arm64, gcc12) / Finalize | ✅ success | view |
| Load dependencies (arm64, gcc12) / Metadata | ✅ success | view |
| Load dependencies (arm64, llvm) / Caching | ✅ success | view |
| Load dependencies (arm64, llvm) / Finalize | ✅ success | view |
| Load dependencies (arm64, llvm) / Metadata | ✅ success | view |
| Load source build cache | ⏩ skipped | view |
| Load wheel dependencies (amd64, 12.6) / Caching | ✅ success | view |
| Load wheel dependencies (amd64, 12.6) / Finalize | ✅ success | view |
| Load wheel dependencies (amd64, 12.6) / Metadata | ✅ success | view |
| Load wheel dependencies (amd64, 13.0) / Caching | ✅ success | view |
| Load wheel dependencies (amd64, 13.0) / Finalize | ✅ success | view |
| Load wheel dependencies (amd64, 13.0) / Metadata | ✅ success | view |
| Load wheel dependencies (arm64, 12.6) / Caching | ✅ success | view |
| Load wheel dependencies (arm64, 12.6) / Finalize | ✅ success | view |
| Load wheel dependencies (arm64, 12.6) / Metadata | ✅ success | view |
| Load wheel dependencies (arm64, 13.0) / Caching | ✅ success | view |
| Load wheel dependencies (arm64, 13.0) / Finalize | ✅ success | view |
| Load wheel dependencies (arm64, 13.0) / Metadata | ✅ success | view |
| Prepare cache clean-up | ✅ success | view |
| Retrieve PR info | ✅ success | view |
⚠️ Required checks (0/6) — 6 missing — declared in .github/required-checks.yml for push
| Required check | Status | Link |
|---|---|---|
| Build and test (amd64, llvm, openmpi) / Dev environment (Debug) | ❌ failure | view |
| Build and test (amd64, llvm, openmpi) / Dev environment (Python) | ❌ failure | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Debug) | ❌ failure | view |
| Build and test (arm64, llvm, openmpi) / Dev environment (Python) | ❌ failure | view |
| Build and test (amd64, gcc12, openmpi) / Dev environment (Debug) | ❌ failure | view |
| Build and test (amd64, gcc12, openmpi) / Dev environment (Python) | ❌ failure | view |
Collaborator
|
Let's land #5113 first to see if that doesn't fix the issue. |
sacpis
approved these changes
Aug 13, 2026
Collaborator
|
Seems like we have a test failure Seems like the test failure is a correct behavior. |
Collaborator
Author
|
It looks like #5113 fixed this issue. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A kernel that allocates qubits but applies no operation to them loses its register entirely. sample() returns no counts at all and get_state() segfaults dereferencing a null SimulationState:
DQE erases an alloca whose only use is a dealloc, and a null_wire whose only use is a sink. That is sound when nothing observes the register, but an entry point's register is observable: sample() implicitly measures every allocated qubit and get_state() returns the whole register. Since #4993 enabled value semantics for local simulators as well, such a kernel now reaches the runtime with no qubits at all.
Keep the allocation when it is the last one in a cudaq-entrypoint function. Partially used registers are unaffected, and dead qubits in non-entry-point functions are still eliminated.
Adds a FileCheck test for both halves of that rule and an execution test asserting the observable contract. Both fail without the fix.