Skip to content
Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
63f3e59
reuse scf builders for qc and qco from old implementation
Apr 9, 2026
e726180
initial support for easier register usage in qc
Apr 9, 2026
0fc693f
add conversion of scf.for
Apr 10, 2026
834047a
add conversion of while op
Apr 10, 2026
aa70f5e
add custom qco.if parser/printer for multiple types
Apr 10, 2026
8a67a7b
add scf.if to qco.if conversion
Apr 11, 2026
217bfc4
support scf conversion from qco to qc
Apr 11, 2026
f385b36
refactor the qc to qco conversion
Apr 12, 2026
8a29b41
store already extracted qubits in qco to qc conversion
Apr 12, 2026
2bcfc13
disable some verifications for qco::IfOp
Apr 12, 2026
380b8a7
add some documentation
Apr 12, 2026
09a0bc7
allow dynamic indices for tensors
Apr 12, 2026
2dd4a4b
add stubs for tests
Apr 12, 2026
3623b13
Merge remote-tracking branch 'upstream/main' into scf-conversions
Apr 12, 2026
74aea0a
adjust qco::IfOp and qco::YieldOp
Apr 12, 2026
4953677
add explicit memref loadOp
Apr 12, 2026
9daab96
add insert/extract of extracted qubits for tensors in the builder
Apr 12, 2026
ba92699
add initial tests
Apr 12, 2026
51a2f57
fix condition in scf::YieldOp conversion to qco
Apr 12, 2026
10e4232
Remove redundant definition in QCProgrambuilder and add index check f…
Apr 13, 2026
cc68bad
refactor QCOProgrambuilder
Apr 13, 2026
b6b0769
fix bug in qc->qco conversion
Apr 13, 2026
acc7ec8
add more tests
Apr 13, 2026
e7c2ee1
fix for operation example in QCProgramBuilder
Apr 13, 2026
d7c6fc9
fixing qc to qco conversion
Apr 13, 2026
052b329
update the QCOProgramBuilder
Apr 13, 2026
6f7907c
add additional test
Apr 13, 2026
560b2d2
fix docstrings of qco.yield
Apr 13, 2026
8422188
add linear type definition
Apr 13, 2026
0da9d67
add more tests
Apr 13, 2026
0fd2992
clean up IfOp parser/printer
Apr 13, 2026
4f3e1ea
Merge remote-tracking branch 'upstream/main' into scf-conversions
Apr 13, 2026
0ea7f1a
adjust docstrings
Apr 14, 2026
69360ab
Merge remote-tracking branch 'upstream/main' into scf-conversions
Apr 14, 2026
24c00a3
fix conversion rules for scf operations in qco to qc
Apr 14, 2026
4c527ea
cleanup code a bit
Apr 14, 2026
b94d119
fix linter issues
Apr 14, 2026
04c887a
use correct SmallVector
Apr 14, 2026
37f1440
use arrayRefs
Apr 14, 2026
f1d0f5b
adjust const usage
Apr 14, 2026
85533f8
address coderabbit comments
Apr 14, 2026
ca7fba5
more coderabbit feedback
Apr 14, 2026
958e059
remove redundant checks
Apr 14, 2026
69a1fe8
add codereview feedback
Apr 14, 2026
607f5cf
extract common functionality in scf builders
Apr 15, 2026
0df39ef
address coderabbit comments
Apr 15, 2026
d169014
simplify scf ops in QCOProgramBuilder
Apr 15, 2026
6fdb5b8
Merge remote-tracking branch 'upstream/main' into scf-conversions
Apr 15, 2026
f658ce0
Apply suggestions from code review
li-mingbao Apr 16, 2026
9680f6a
apply codereview feedback
Apr 16, 2026
7ab958a
add qco.if parser test
Apr 16, 2026
c6e484a
fixing some docstrings
Apr 16, 2026
a79fb69
remove the StringAttr marker in the qc to qco conversion
Apr 16, 2026
964d7b0
add accidently removed line back
Apr 16, 2026
02ccb40
support only dynamic indices for memref.load
Apr 16, 2026
be3dc79
add missing argument in qco.if example
Apr 16, 2026
52aff06
improve tracking of already loaded qubits
Apr 16, 2026
56107ba
fix linter issues
Apr 16, 2026
d661f1e
restrict memrefLoad to nested regions and add details section
Apr 16, 2026
3b1e25e
address coderabbit comments
Apr 20, 2026
2e29ffc
Merge branch 'main' into scf-conversions
denialhaag Apr 29, 2026
5647b54
Fix rebase and adapt to new include style
denialhaag Apr 29, 2026
5bb31a5
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 29, 2026
5a681ef
Actually fix rebase and adapt to new include style
denialhaag Apr 29, 2026
ec53027
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 29, 2026
b0b6bb1
fix some coderabbit comments
Apr 29, 2026
5c73a7a
add qco.if test if mixed qubit and qtensor type
Apr 29, 2026
8fc7fd3
🎨 Streamline QC builder code
burgholzer May 5, 2026
18b2b4a
🎨 Streamline QCo builder code
burgholzer May 5, 2026
63d0396
🎨 Small improvements for QC to QCO conversion
burgholzer May 5, 2026
473019d
🎨 Minor tweaks to QCO<->QC conversion
burgholzer May 5, 2026
ad5dfe7
📝 Add changelog entry
burgholzer May 5, 2026
c9bf52d
Merge branch 'main' into fork/li-mingbao/scf-conversions
burgholzer May 6, 2026
1745374
fix docstrings
May 6, 2026
a0a7e24
modify qco.if print from qubits to generics args
May 6, 2026
aa77eed
Merge remote-tracking branch 'upstream/main' into scf-conversions
May 6, 2026
85539f6
apply coderabbit suggestions
May 6, 2026
a32f751
adjust ifOp tests
May 11, 2026
c45b2fd
Merge remote-tracking branch 'upstream/main' into scf-conversions
May 11, 2026
93935fb
use llvm::to_vector for ValueRange to SmallVector conversion
May 11, 2026
d9bcd56
fix flaky test
May 11, 2026
5231bd7
remove debug statements
May 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,28 @@ class QCProgramBuilder final : public ImplicitLocOpBuilder {
*/
QubitRegister allocQubitRegister(int64_t size);

/**
* @brief Explicitly loads a qubit from a memref
*
* @details Explicitly loads a qubit from a memref at the given index. This
* builder should only be called in a nested region inside the main function.
* The same index cannot be used to load a value multiple times in the same
* nested region.
*
* @param memref Source memref
* @param index The index from where the qubit is loaded
* @return The loaded qubit
*
* @par Example:
* ```c++
* auto q0 = builder.memrefLoad(memref, index);
* ```
* ```mlir
* %q0 = memref.load %memref[%index] : memref<3x!qc.qubit>
* ```
*/
Value memrefLoad(Value memref, Value index);
Comment thread
burgholzer marked this conversation as resolved.
Comment thread
li-mingbao marked this conversation as resolved.

/**
* @brief A small structure representing a single classical bit within a
* classical register.
Expand Down Expand Up @@ -924,6 +946,115 @@ class QCProgramBuilder final : public ImplicitLocOpBuilder {
*/
QCProgramBuilder& dealloc(Value qubit);

//===--------------------------------------------------------------------===//
// SCF operations
//===--------------------------------------------------------------------===//

/**
* @brief Construct a scf.for operation
Comment thread
burgholzer marked this conversation as resolved.
Outdated
*
* @param lowerbound Lower bound of the loop
* @param upperbound Upper bound of the loop
* @param step Step size of the loop
* @param body Function that builds the body of the for operation
* @return Reference to this builder for method chaining
*
* @par Example:
* ```c++
* builder.scfFor(lb, ub, step, [&](Value iv) {
* auto q0 = builder.memrefLoad(memref, iv);
* builder.h(q0);
* });
* ```
Comment thread
coderabbitai[bot] marked this conversation as resolved.
* ```mlir
* scf.for %iv = %lb to %ub step %step {
* %q0 = memref.load %memref[%iv] : memref<3x!qc.qubit>
* qc.h %q0 : !qc.qubit
* scf.yield
* }
Comment thread
burgholzer marked this conversation as resolved.
* ```
*/
QCProgramBuilder& scfFor(const std::variant<int64_t, Value>& lowerbound,
const std::variant<int64_t, Value>& upperbound,
const std::variant<int64_t, Value>& step,
const function_ref<void(Value)>& body);

/**
* @brief Construct a scf.while operation
*
* @param beforeBody Function that builds the before body of the while
* operation
* @param afterBody Function that builds the after body of the while operation
* @return Reference to this builder for method chaining
*
* @par Example:
* ```c++
* builder.scfWhile([&] {
* auto res = builder.measure(q0);
* builder.scfCondition(res);
* }, [&] {
* builder.h(q0);
* });
* ```
* ```mlir
* scf.while : () -> () {
* %res = qc.measure %q0 : !qc.qubit -> i1
* scf.condition(%res)
* } do {
* qc.h %q0 : !qc.qubit
* scf.yield
* }
* ```
*/
QCProgramBuilder& scfWhile(const function_ref<void()>& beforeBody,
const function_ref<void()>& afterBody);

/**
* @brief Construct a scf.if operation
*
* @param condition Condition for the if operation
* @param thenBody Function that builds the then body of the if operation
* @param elseBody Function that builds the else body of the if operation
* @return Reference to this builder for method chaining
*
* @par Example:
* ```c++
* builder.scfIf(condition, [&] {
* builder.x(q0);
* }, [&] {
* builder.z(q0);
* });
* ```
* ```mlir
* scf.if %condition {
* qc.x %q0 : !qc.qubit
* scf.yield
* } else {
* qc.z %q0 : !qc.qubit
* scf.yield
* }
* ```
Comment thread
denialhaag marked this conversation as resolved.
*/
QCProgramBuilder& scfIf(const std::variant<bool, Value>& condition,
const function_ref<void()>& thenBody,
const function_ref<void()>& elseBody = nullptr);

/**
* @brief Construct a scf.condition operation
*
* @param condition Condition for the condition operation
* @return Reference to this builder for method chaining
*
* @par Example:
* ```c++
* builder.scfCondition(condition);
* ```
* ```mlir
* scf.condition(%condition)
* ```
*/
QCProgramBuilder& scfCondition(Value condition);

//===--------------------------------------------------------------------===//
// Finalization
//===--------------------------------------------------------------------===//
Expand Down Expand Up @@ -966,6 +1097,12 @@ class QCProgramBuilder final : public ImplicitLocOpBuilder {
/// Track allocated MemRefs for automatic deallocation
DenseSet<Value> allocatedMemrefs;

/// Per-region map of memrefs and their loaded indices
DenseMap<Region*, DenseMap<Value, DenseSet<Value>>> loadedQubits;

/// Stack of the nested regions where the insertion point of the builder is
SmallVector<Region*> regionStack;

/// Check if the builder has been finalized
void checkFinalized() const;

Expand Down
Loading
Loading