Skip to content

Rework operand sorting regarding decompositions - #3393

Open
paul0403 wants to merge 20 commits into
mainfrom
paul0403/ssot_goid_sorting
Open

paul0403 wants to merge 20 commits into
mainfrom
paul0403/ssot_goid_sorting

Conversation

@paul0403

@paul0403 paul0403 commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Context:
Rework various operand sorting regarding decomposition to have a single source of truth.

Currently, an operator's arguments are written down in three different orders, and different parts of the code read different ones:

  1. Operand order. The frontend lowering emits operands in declaration order, the order set by PennyLane's Operator2._primitive_bind_call. The compiler also hands operands to a rule in this order, verbatim, during --decompose-lowering.
  2. Sorted order. param_map and qubit_map are MLIR dictionary attributes, so MLIR always sorts them by name. For this reason, the frontend's GraphOpID parsers sorted their entries by name.
  3. Non-deterministic llvm::StringMap order. The C++ getWireLens() and getDynamicShape() return llvm::StringMap, which iterates in non-deterministic order. That order is what the on-demand path passes to Python, since it rebuilds python callback args via the DecomposableGate::get*() methods.

A rule only works if its input layout matches the operands it receives. Each order was used somewhere, so any operator whose declaration order differs from alphabetical order could break. This produced four bugs:


Description of the Change:

Python changes:
It is important to note that we have been operating under a misconception this whole time: just because MLIR dictionary attribute is sorted, does not mean we need to send a sorted dictionary into the dictionary attribute builder.

In short, this PR aims to remove all manual alphabetical sorting of the operands except when building the ID string in the frontend, since that's the only place that actually needs sorting (to match ID strings with the ID string produced from the compiler).

cpp changes:
The DecomposableGate::get*() methods now return llvm::Smallvector<std::pair<std::string, ...>> instead of llvm::StringMap to guarantee iteration order when rebuilding on-demand rule python callback args.

Noteworthily, OperatorOp must retrieve the operand order from the dinctionary attribute order. So a new helper, getEntriesInOperandOrder, reading param_map/qubit_map and stable-sorts the entries by their first operand index, was added to achieve this.


Benefits:
Correctness.
SemiAdder works correctly.
Single source of truth for operand order regarding decompositions.

Possible Drawbacks:
None

Related GitHub Issues:
Fixes #3337
[sc-133791]

Assisted by Opus 5.5

@codecov

codecov Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.22%. Comparing base (02615a3) to head (addc7eb).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3393   +/-   ##
=======================================
  Coverage   96.21%   96.22%           
=======================================
  Files         176      176           
  Lines       21583    21580    -3     
  Branches     2160     2158    -2     
=======================================
- Hits        20766    20765    -1     
+ Misses        631      630    -1     
+ Partials      186      185    -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@paul0403
paul0403 requested review from kipawaa and maliasadi October 26, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Graph decomposition passes multi-register wires to compiled rules in the wrong order (wrong SemiAdder results)

1 participant