From c5c936116fd290ac612fe481830d1b44d1baaa3f Mon Sep 17 00:00:00 2001 From: Ben Howe <141149032+bmhowe23@users.noreply.github.com> Date: Wed, 8 Jan 2025 07:56:16 -0800 Subject: [PATCH 1/4] [test] Fix evolve test repeatability issue (#2496) --- python/tests/operator/test_evolve_simulators.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/tests/operator/test_evolve_simulators.py b/python/tests/operator/test_evolve_simulators.py index fa733537c1..85e2b6b9dc 100644 --- a/python/tests/operator/test_evolve_simulators.py +++ b/python/tests/operator/test_evolve_simulators.py @@ -172,6 +172,9 @@ def do_something(): def test_evolve(): + # Set random seed for shots-based observe test. + cudaq.set_random_seed(13) + # Qubit Hamiltonian hamiltonian = 2 * np.pi * 0.1 * spin.x(0) @@ -242,6 +245,9 @@ def test_evolve(): def test_evolve_async(): + # Set random seed for shots-based observe test. + cudaq.set_random_seed(13) + # Qubit Hamiltonian hamiltonian = 2 * np.pi * 0.1 * spin.x(0) From d2bed4c0b4df29d481b3febb69128100e5c0682f Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 8 Jan 2025 11:09:49 -0800 Subject: [PATCH 2/4] Add a few state-related cc ops (#2354) * Add a few state-related cc ops Signed-off-by: Anna Gringauze * Fix test_argument_conversion Signed-off-by: Anna Gringauze * Add printing in failing tests Signed-off-by: Anna Gringauze * Add printing in failing tests Signed-off-by: Anna Gringauze * Fix failing tests Signed-off-by: Anna Gringauze * Address CR comments Signed-off-by: Anna Gringauze * Fix comment Signed-off-by: Anna Gringauze * Address CR comments Signed-off-by: Anna Gringauze --------- Signed-off-by: Anna Gringauze --- .../workflows/config/spelling_allowlist.txt | 1 + docs/sphinx/targets/cpp/infleqtion.cpp | 14 +-- .../cudaq/Optimizer/Dialect/Quake/QuakeOps.td | 86 ++++++++++++++ include/cudaq/Optimizer/Transforms/Passes.td | 5 +- lib/Frontend/nvqpp/ConvertExpr.cpp | 13 +-- lib/Optimizer/CodeGen/QuakeToCodegen.cpp | 90 ++++++++++++++- lib/Optimizer/Transforms/DeleteStates.cpp | 109 +++++++----------- python/cudaq/kernel/ast_bridge.py | 9 +- python/cudaq/kernel/kernel_builder.py | 10 +- .../cudaq/platform/py_alt_launch_kernel.cpp | 1 + .../kernel/test_kernel_qvector_state_init.py | 29 +++-- runtime/common/ArgumentConversion.cpp | 24 +--- runtime/common/BaseRemoteRESTQPU.h | 1 + runtime/cudaq/builder/kernel_builder.cpp | 11 +- runtime/test/test_argument_conversion.cpp | 20 +--- test/AST-Quake/qalloc_state.cpp | 9 +- test/Quake/delete_states.qke | 80 +++++-------- test/Quake/roundtrip-ops.qke | 22 ++++ 18 files changed, 323 insertions(+), 211 deletions(-) diff --git a/.github/workflows/config/spelling_allowlist.txt b/.github/workflows/config/spelling_allowlist.txt index 19fcb2d34f..f8a892f403 100644 --- a/.github/workflows/config/spelling_allowlist.txt +++ b/.github/workflows/config/spelling_allowlist.txt @@ -108,6 +108,7 @@ SLURM SVD Stim Superpositions +Superstaq TBI TCP TableGen diff --git a/docs/sphinx/targets/cpp/infleqtion.cpp b/docs/sphinx/targets/cpp/infleqtion.cpp index 4a61b71571..de2f57f0d5 100644 --- a/docs/sphinx/targets/cpp/infleqtion.cpp +++ b/docs/sphinx/targets/cpp/infleqtion.cpp @@ -2,8 +2,8 @@ // ``` // nvq++ --target infleqtion infleqtion.cpp -o out.x && ./out.x // ``` -// This will submit the job to the Infleqtion's ideal simulator, -// cq_sqale_simulator (default). Alternatively, we can enable hardware noise +// This will submit the job to the ideal simulator for Infleqtion, +// `cq_sqale_simulator` (default). Alternatively, we can enable hardware noise // model simulation by specifying `noise-sim` to the flag `--infleqtion-method`, // e.g., // ``` @@ -17,9 +17,9 @@ // nvq++ --target infleqtion --infleqtion-machine cq_sqale_qpu // --infleqtion-method dry-run infleqtion.cpp -o out.x && ./out.x // ``` -// Note: If targeting ideal cloud simulation, `--infleqtion-machine -// cq_sqale_simulator` is optional since it is the default configuration if not -// provided. +// Note: If targeting ideal cloud simulation, +// `--infleqtion-machine cq_sqale_simulator` is optional since it is the +// default configuration if not provided. #include #include @@ -38,7 +38,7 @@ struct ghz { }; int main() { - // Submit to infleqtion asynchronously (e.g., continue executing + // Submit to Infleqtion asynchronously (e.g., continue executing // code in the file until the job has been returned). auto future = cudaq::sample_async(ghz{}); // ... classical code to execute in the meantime ... @@ -58,7 +58,7 @@ int main() { auto async_counts = readIn.get(); async_counts.dump(); - // OR: Submit to infleqtion synchronously (e.g., wait for the job + // OR: Submit to Infleqtion synchronously (e.g., wait for the job // result to be returned before proceeding). auto counts = cudaq::sample(ghz{}); counts.dump(); diff --git a/include/cudaq/Optimizer/Dialect/Quake/QuakeOps.td b/include/cudaq/Optimizer/Dialect/Quake/QuakeOps.td index d964cb415e..9a2af0ee62 100644 --- a/include/cudaq/Optimizer/Dialect/Quake/QuakeOps.td +++ b/include/cudaq/Optimizer/Dialect/Quake/QuakeOps.td @@ -1397,4 +1397,90 @@ def CustomUnitarySymbolOp : }]; } +//===----------------------------------------------------------------------===// +// Quantum states +//===----------------------------------------------------------------------===// + +def quake_CreateStateOp : QuakeOp<"create_state", [Pure]> { + let summary = "Create state from data"; + let description = [{ + This operation takes a pointer to state data and creates a quantum state, + where state data is a pointer to an array of float or complex numbers. + The operation can be optimized away in DeleteStates pass, or replaced + by an intrinsic runtime call on simulators. + + ```mlir + %0 = quake.create_state %data %len : (!cc.ptr x 8>>, i64) -> !cc.ptr + ``` + }]; + + let arguments = (ins + cc_PointerType:$data, + AnySignlessInteger:$length + ); + let results = (outs cc_PointerType:$result); + let assemblyFormat = [{ + $data `,` $length `:` functional-type(operands, results) attr-dict + }]; +} + +def QuakeOp_DeleteStateOp : QuakeOp<"delete_state", [] > { + let summary = "Delete quantum state"; + let description = [{ + This operation takes a pointer to the state and deletes the state object. + The operation can be created in in DeleteStates pass, and replaced later + by an intrinsic runtime call on simulators. + + ```mlir + quake.delete_state %state : !cc.ptr + ``` + }]; + + let arguments = (ins cc_PointerType:$state); + let results = (outs); + let assemblyFormat = [{ + $state `:` type(operands) attr-dict + }]; +} + +def quake_GetNumberOfQubitsOp : QuakeOp<"get_number_of_qubits", [Pure] > { + let summary = "Get number of qubits from a quantum state"; + let description = [{ + This operation takes a pointer to the state as an argument and returns + a number of qubits in the state. The operation can be optimized away in + some passes like ReplaceStateByKernel or DeleteStates, or replaced by an + intrinsic runtime call when the target is one of the simulators. + + ```mlir + %0 = quake.get_number_of_qubits %state : (!cc.ptr) -> i64 + ``` + }]; + + let arguments = (ins cc_PointerType:$state); + let results = (outs AnySignlessInteger:$result); + let assemblyFormat = [{ + $state `:` functional-type(operands, results) attr-dict + }]; +} + +def QuakeOp_GetStateOp : QuakeOp<"get_state", [Pure] > { + let summary = "Get state from kernel with the provided name."; + let description = [{ + This operation is created by argument synthesis of state pointer arguments + for quantum devices. It takes a kernel name as ASCIIZ string literal value + and returns the kernel's quantum state. The operation is replaced by a call + to the kernel with the provided name in ReplaceStateByKernel pass. + + ```mlir + %0 = quake.get_state "callee" : !cc.ptr + ``` + }]; + + let arguments = (ins StrAttr:$calleeName); + let results = (outs cc_PointerType:$result); + let assemblyFormat = [{ + $calleeName `:` qualified(type(results)) attr-dict + }]; +} + #endif // CUDAQ_OPTIMIZER_DIALECT_QUAKE_OPS diff --git a/include/cudaq/Optimizer/Transforms/Passes.td b/include/cudaq/Optimizer/Transforms/Passes.td index bbd1144ae9..38189117f2 100644 --- a/include/cudaq/Optimizer/Transforms/Passes.td +++ b/include/cudaq/Optimizer/Transforms/Passes.td @@ -778,9 +778,8 @@ def DeleteStates : Pass<"delete-states", "mlir::ModuleOp"> { func.func @foo() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { %c8_i64 = arith.constant 8 : i64 %0 = cc.address_of @foo.rodata_synth_0 : !cc.ptr x 8>> - %3 = cc.cast %0 : (!cc.ptr x 8>>) -> !cc.ptr - %4 = call @__nvqpp_cudaq_state_createFromData_fp32(%3, %c8_i64) : (!cc.ptr, i64) -> !cc.ptr - %5 = call @__nvqpp_cudaq_state_numberOfQubits(%4) : (!cc.ptr) -> i64 + %4 = cc.create_state %3, %c8_i64 : (!cc.ptr x 8>>, i64) -> !cc.ptr + %5 = cc.get_number_of_qubits %4 : (!cc.ptr) -> i64 %6 = quake.alloca !quake.veq[%5 : i64] %7 = quake.init_state %6, %4 : (!quake.veq, !cc.ptr) -> !quake.veq diff --git a/lib/Frontend/nvqpp/ConvertExpr.cpp b/lib/Frontend/nvqpp/ConvertExpr.cpp index 39f4b71942..5be475ccb7 100644 --- a/lib/Frontend/nvqpp/ConvertExpr.cpp +++ b/lib/Frontend/nvqpp/ConvertExpr.cpp @@ -2698,19 +2698,12 @@ bool QuakeBridgeVisitor::VisitCXXConstructExpr(clang::CXXConstructExpr *x) { initials = load.getPtrvalue(); } if (isStateType(initials.getType())) { - IRBuilder irBuilder(builder.getContext()); - auto mod = - builder.getBlock()->getParentOp()->getParentOfType(); - auto result = - irBuilder.loadIntrinsic(mod, getNumQubitsFromCudaqState); - assert(succeeded(result) && "loading intrinsic should never fail"); Value state = initials; auto i64Ty = builder.getI64Type(); - auto numQubits = builder.create( - loc, i64Ty, getNumQubitsFromCudaqState, ValueRange{state}); + auto numQubits = + builder.create(loc, i64Ty, state); auto veqTy = quake::VeqType::getUnsized(ctx); - Value alloc = builder.create(loc, veqTy, - numQubits.getResult(0)); + Value alloc = builder.create(loc, veqTy, numQubits); return pushValue(builder.create( loc, veqTy, alloc, state)); } diff --git a/lib/Optimizer/CodeGen/QuakeToCodegen.cpp b/lib/Optimizer/CodeGen/QuakeToCodegen.cpp index 36571a7511..cc8e2c9cf7 100644 --- a/lib/Optimizer/CodeGen/QuakeToCodegen.cpp +++ b/lib/Optimizer/CodeGen/QuakeToCodegen.cpp @@ -8,6 +8,9 @@ #include "QuakeToCodegen.h" #include "CodeGenOps.h" +#include "cudaq/Optimizer/Builder/Intrinsics.h" +#include "cudaq/Optimizer/CodeGen/Passes.h" +#include "cudaq/Optimizer/CodeGen/QIRFunctionNames.h" #include "cudaq/Optimizer/Dialect/CC/CCOps.h" #include "cudaq/Optimizer/Dialect/Quake/QuakeOps.h" #include "mlir/Conversion/LLVMCommon/ConversionTarget.h" @@ -62,10 +65,95 @@ class ExpandComplexCast : public OpRewritePattern { return success(); } }; + +class CreateStateOpPattern : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(quake::CreateStateOp createStateOp, + PatternRewriter &rewriter) const override { + auto module = createStateOp->getParentOfType(); + auto loc = createStateOp.getLoc(); + auto ctx = createStateOp.getContext(); + auto buffer = createStateOp.getOperand(0); + auto size = createStateOp.getOperand(1); + + auto bufferTy = buffer.getType(); + auto ptrTy = cast(bufferTy); + auto arrTy = cast(ptrTy.getElementType()); + auto eleTy = arrTy.getElementType(); + auto is64Bit = isa(eleTy); + + if (auto cTy = dyn_cast(eleTy)) + is64Bit = isa(cTy.getElementType()); + + auto createStateFunc = is64Bit ? cudaq::createCudaqStateFromDataFP64 + : cudaq::createCudaqStateFromDataFP32; + cudaq::IRBuilder irBuilder(ctx); + auto result = irBuilder.loadIntrinsic(module, createStateFunc); + assert(succeeded(result) && "loading intrinsic should never fail"); + + auto stateTy = cudaq::cc::StateType::get(ctx); + auto statePtrTy = cudaq::cc::PointerType::get(stateTy); + auto i8PtrTy = cudaq::cc::PointerType::get(rewriter.getI8Type()); + auto cast = rewriter.create(loc, i8PtrTy, buffer); + + rewriter.replaceOpWithNewOp( + createStateOp, statePtrTy, createStateFunc, ValueRange{cast, size}); + return success(); + } +}; + +class DeleteStateOpPattern : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(quake::DeleteStateOp deleteStateOp, + PatternRewriter &rewriter) const override { + auto module = deleteStateOp->getParentOfType(); + auto ctx = deleteStateOp.getContext(); + auto state = deleteStateOp.getOperand(); + + cudaq::IRBuilder irBuilder(ctx); + auto result = irBuilder.loadIntrinsic(module, cudaq::deleteCudaqState); + assert(succeeded(result) && "loading intrinsic should never fail"); + + rewriter.replaceOpWithNewOp(deleteStateOp, std::nullopt, + cudaq::deleteCudaqState, + mlir::ValueRange{state}); + return success(); + } +}; + +class GetNumberOfQubitsOpPattern + : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(quake::GetNumberOfQubitsOp getNumQubitsOp, + PatternRewriter &rewriter) const override { + auto module = getNumQubitsOp->getParentOfType(); + auto ctx = getNumQubitsOp.getContext(); + auto state = getNumQubitsOp.getOperand(); + + cudaq::IRBuilder irBuilder(ctx); + auto result = + irBuilder.loadIntrinsic(module, cudaq::getNumQubitsFromCudaqState); + assert(succeeded(result) && "loading intrinsic should never fail"); + + rewriter.replaceOpWithNewOp( + getNumQubitsOp, rewriter.getI64Type(), + cudaq::getNumQubitsFromCudaqState, state); + return success(); + } +}; + } // namespace void cudaq::codegen::populateQuakeToCodegenPatterns( mlir::RewritePatternSet &patterns) { auto *ctx = patterns.getContext(); - patterns.insert(ctx); + patterns + .insert(ctx); } diff --git a/lib/Optimizer/Transforms/DeleteStates.cpp b/lib/Optimizer/Transforms/DeleteStates.cpp index 0c68f47ad0..a4ff3948f2 100644 --- a/lib/Optimizer/Transforms/DeleteStates.cpp +++ b/lib/Optimizer/Transforms/DeleteStates.cpp @@ -29,104 +29,78 @@ namespace cudaq::opt { using namespace mlir; namespace { - -static bool isCall(Operation *callOp, std::vector &&names) { - if (callOp) { - if (auto createStateCall = dyn_cast(callOp)) { - if (auto calleeAttr = createStateCall.getCalleeAttr()) { - auto funcName = calleeAttr.getValue().str(); - if (std::find(names.begin(), names.end(), funcName) != names.end()) - return true; - } - } - } - return false; -} - -static bool isCreateStateCall(Operation *callOp) { - return isCall(callOp, {cudaq::createCudaqStateFromDataFP64, - cudaq::createCudaqStateFromDataFP32}); -} - -static bool isNumberOfQubitsCall(Operation *callOp) { - return isCall(callOp, {cudaq::getNumQubitsFromCudaqState}); -} - -/// For a call to `__nvqpp_cudaq_state_createFromData_fpXX`, get the number of -/// qubits allocated. -static std::size_t getStateSize(Operation *callOp) { - if (isCreateStateCall(callOp)) { - if (auto createStateCall = dyn_cast(callOp)) { - auto sizeOperand = createStateCall.getOperand(1); - auto defOp = sizeOperand.getDefiningOp(); - while (defOp && !dyn_cast(defOp)) - defOp = defOp->getOperand(0).getDefiningOp(); - if (auto constOp = dyn_cast(defOp)) - return constOp.getValue().cast().getInt(); - } +/// For a `quake.create_state`, get the number of qubits allocated. +static std::size_t getStateSize(Operation *op) { + if (auto createStateOp = dyn_cast(op)) { + auto sizeOperand = createStateOp.getOperand(1); + auto defOp = sizeOperand.getDefiningOp(); + while (defOp && !dyn_cast(defOp)) + defOp = defOp->getOperand(0).getDefiningOp(); + if (auto constOp = dyn_cast(defOp)) + return constOp.getValue().cast().getInt(); } - callOp->emitError("Cannot compute number of qubits"); + op->emitError("Cannot compute number of qubits from createStateOp"); return 0; } // clang-format off -/// Remove `__nvqpp_cudaq_state_numberOfQubits` calls. +/// Replace `quake.get_number_of_qubits` by a constant. /// ``` -/// %1 = arith.constant 8 : i64 -/// %2 = call @__nvqpp_cudaq_state_createFromData_fp32(%0, %1) : (!cc.ptr, i64) -> !cc.ptr -/// %3 = call @__nvqpp_cudaq_state_numberOfQubits(%2) : (!cc.ptr) -> i64 +/// %c8_i64 = arith.constant 8 : i64 +/// %2 = quake.create_state %3, %c8_i64 : (!cc.ptr, i64) -> !cc.ptr +/// %3 = quake.get_number_of_qubits %2 : i64 /// ... /// ─────────────────────────────────────────── -/// %1 = arith.constant 8 : i64 -/// %2 = call @__nvqpp_cudaq_state_createFromData_fp32(%0, %1) : (!cc.ptr, i64) -> !cc.ptr -/// %5 = arith.constant 3 : i64 +/// %c8_i64 = arith.constant 8 : i64 +/// %2 = quake.create_state %3, %c8_i64 : (!cc.ptr, i64) -> !cc.ptr +/// %3 = arith.constant 3 : i64 /// ``` // clang-format on -class NumberOfQubitsPattern : public OpRewritePattern { +class NumberOfQubitsPattern + : public OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; - LogicalResult matchAndRewrite(func::CallOp callOp, + LogicalResult matchAndRewrite(quake::GetNumberOfQubitsOp op, PatternRewriter &rewriter) const override { - if (isNumberOfQubitsCall(callOp)) { - auto createStateOp = callOp.getOperand(0).getDefiningOp(); - if (isCreateStateCall(createStateOp)) { - auto size = getStateSize(createStateOp); - rewriter.replaceOpWithNewOp( - callOp, std::countr_zero(size), rewriter.getI64Type()); - return success(); - } + auto stateOp = op.getOperand(); + if (auto createStateOp = stateOp.getDefiningOp()) { + auto size = getStateSize(createStateOp); + rewriter.replaceOpWithNewOp( + op, std::countr_zero(size), rewriter.getI64Type()); + return success(); } return failure(); } }; // clang-format off -/// Replace calls to `__nvqpp_cudaq_state_numberOfQubits` by a constant. +/// Remove `quake.create_state` instructions and pass their data directly to +/// the `quake.state_init` instruction instead. /// ``` /// %2 = cc.cast %1 : (!cc.ptr x 8>>) -> !cc.ptr -/// %3 = call @__nvqpp_cudaq_state_createFromData_fp32(%2, %c8_i64) : (!cc.ptr, i64) -> !cc.ptr +/// %3 = quake.create_state %3, %c8_i64 : (!cc.ptr, i64) -> !cc.ptr /// %4 = quake.alloca !quake.veq[%0 : i64] /// %5 = quake.init_state %4, %3 : (!quake.veq, !cc.ptr) -> !quake.veq /// ─────────────────────────────────────────── /// ... -/// %3 = call @__nvqpp_cudaq_state_createFromData_fp32(%2, %c8_i64) : (!cc.ptr, i64) -> !cc.ptr /// %4 = quake.alloca !quake.veq[%0 : i64] /// %5 = quake.init_state %4, %1 : (!quake.veq, !cc.ptr x 8>>) -> !quake.veq /// ``` // clang-format on + class StateToDataPattern : public OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(quake::InitializeStateOp initState, PatternRewriter &rewriter) const override { - auto stateOp = initState.getOperand(1).getDefiningOp(); + auto state = initState.getOperand(1); auto targets = initState.getTargets(); - if (isCreateStateCall(stateOp)) { - auto dataOp = stateOp->getOperand(0); - if (auto cast = dyn_cast(dataOp.getDefiningOp())) + if (auto createStateOp = state.getDefiningOp()) { + auto dataOp = createStateOp->getOperand(0); + if (auto cast = dataOp.getDefiningOp()) dataOp = cast.getOperand(); rewriter.replaceOpWithNewOp( initState, targets.getType(), targets, dataOp); @@ -163,10 +137,8 @@ class DeleteStatesPass llvm::SmallVector usedStates; func.walk([&](Operation *op) { - if (isCreateStateCall(op)) { - if (op->getUses().empty()) - op->erase(); - else + if (isa(op)) { + if (!op->getUses().empty()) usedStates.push_back(op); } }); @@ -178,15 +150,14 @@ class DeleteStatesPass func.walk([&](Operation *op) { if (isa(op)) { auto loc = op->getLoc(); - auto deleteState = cudaq::deleteCudaqState; - auto result = irBuilder.loadIntrinsic(module, deleteState); + auto result = + irBuilder.loadIntrinsic(module, cudaq::deleteCudaqState); assert(succeeded(result) && "loading intrinsic should never fail"); builder.setInsertionPoint(op); for (auto createStateOp : usedStates) { - auto results = cast(createStateOp).getResults(); - builder.create(loc, std::nullopt, deleteState, - results); + auto result = cast(createStateOp); + builder.create(loc, result); } } }); diff --git a/python/cudaq/kernel/ast_bridge.py b/python/cudaq/kernel/ast_bridge.py index 79299f052b..ba5e664ea8 100644 --- a/python/cudaq/kernel/ast_bridge.py +++ b/python/cudaq/kernel/ast_bridge.py @@ -2250,11 +2250,9 @@ def bodyBuilder(iterVal): # handle `cudaq.qvector(state)` statePtr = self.ifNotPointerThenStore(valueOrPtr) - symName = '__nvqpp_cudaq_state_numberOfQubits' - load_intrinsic(self.module, symName) i64Ty = self.getIntegerType() - numQubits = func.CallOp([i64Ty], symName, - [statePtr]).result + numQubits = quake.GetNumberOfQubitsOp(i64Ty, + statePtr).result veqTy = quake.VeqType.get(self.ctx) qubits = quake.AllocaOp(veqTy, size=numQubits).result @@ -3876,6 +3874,9 @@ def visit_Name(self, node): if cc.StdvecType.isinstance(eleTy): self.pushValue(value) return + if cc.StateType.isinstance(eleTy): + self.pushValue(value) + return loaded = cc.LoadOp(value).result self.pushValue(loaded) elif cc.CallableType.isinstance( diff --git a/python/cudaq/kernel/kernel_builder.py b/python/cudaq/kernel/kernel_builder.py index bb26b5f22b..3e83f16147 100644 --- a/python/cudaq/kernel/kernel_builder.py +++ b/python/cudaq/kernel/kernel_builder.py @@ -777,10 +777,8 @@ def qalloc(self, initializer=None): if isinstance(initializer, cudaq_runtime.State): statePtr = self.capturedDataStorage.storeCudaqState(initializer) - symName = '__nvqpp_cudaq_state_numberOfQubits' - load_intrinsic(self.module, symName) i64Ty = self.getIntegerType() - numQubits = func.CallOp([i64Ty], symName, [statePtr]).result + numQubits = quake.GetNumberOfQubitsOp(i64Ty, statePtr).result veqTy = quake.VeqType.get(self.ctx) qubits = quake.AllocaOp(veqTy, size=numQubits).result @@ -816,11 +814,9 @@ def qalloc(self, initializer=None): if cc.StateType.isinstance(valueTy): statePtr = initializer.mlirValue - symName = '__nvqpp_cudaq_state_numberOfQubits' - load_intrinsic(self.module, symName) i64Ty = self.getIntegerType() - numQubits = func.CallOp([i64Ty], symName, - [statePtr]).result + numQubits = quake.GetNumberOfQubitsOp(i64Ty, + statePtr).result veqTy = quake.VeqType.get(self.ctx) qubits = quake.AllocaOp(veqTy, size=numQubits).result diff --git a/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp b/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp index c5f8580f1d..e095a6d712 100644 --- a/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp +++ b/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp @@ -547,6 +547,7 @@ MlirModule synthesizeKernel(const std::string &name, MlirModule module, pm.addNestedPass( cudaq::opt::createArgumentSynthesisPass(kernels, substs)); pm.addNestedPass(createCanonicalizerPass()); + pm.addPass(opt::createDeleteStates()); // Run state preparation for quantum devices (or their emulation) only. // Simulators have direct implementation of state initialization diff --git a/python/tests/kernel/test_kernel_qvector_state_init.py b/python/tests/kernel/test_kernel_qvector_state_init.py index 25b527311a..fbc703fe37 100644 --- a/python/tests/kernel/test_kernel_qvector_state_init.py +++ b/python/tests/kernel/test_kernel_qvector_state_init.py @@ -32,11 +32,16 @@ def test_kernel_synthesis_complex(): def kernel(vec: cudaq.State): q = cudaq.qvector(vec) + counts = cudaq.sample(kernel, state) + assert '00' in counts + assert '10' in counts + assert len(counts) == 2 + synthesized = cudaq.synthesize(kernel, state) counts = cudaq.sample(synthesized) - print(counts) - assert '10' in counts assert '00' in counts + assert '10' in counts + assert len(counts) == 2 # float @@ -46,7 +51,7 @@ def kernel(vec: cudaq.State): def test_kernel_float_params_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') f = np.array([1. / np.sqrt(2.), 0., 0., 1. / np.sqrt(2.)], dtype=float) @@ -76,7 +81,7 @@ def test_kernel_float_params_f32(): @skipIfNvidiaFP64NotInstalled def test_kernel_complex_params_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=complex) @@ -95,7 +100,7 @@ def kernel(vec: cudaq.State): @skipIfNvidiaFP64NotInstalled def test_kernel_complex128_params_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=np.complex128) @@ -114,7 +119,7 @@ def kernel(vec: cudaq.State): @skipIfNvidiaFP64NotInstalled def test_kernel_complex64_params_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=np.complex64) @@ -172,7 +177,7 @@ def test_kernel_complex_params_f32(): @skipIfNvidiaFP64NotInstalled def test_kernel_complex_capture_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=complex) @@ -191,7 +196,7 @@ def kernel(): @skipIfNvidiaFP64NotInstalled def test_kernel_complex128_capture_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=np.complex128) @@ -210,7 +215,7 @@ def kernel(): @skipIfNvidiaFP64NotInstalled def test_kernel_complex128_capture_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=np.complex64) @@ -271,7 +276,7 @@ def test_kernel_complex_capture_f32(): @skipIfNvidiaFP64NotInstalled def test_kernel_simulation_dtype_complex_params_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=cudaq.complex()) @@ -309,7 +314,7 @@ def kernel(vec: cudaq.State): @skipIfNvidiaFP64NotInstalled def test_kernel_simulation_dtype_capture_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') c = np.array([1. / np.sqrt(2.) + 0j, 0., 0., 1. / np.sqrt(2.)], dtype=cudaq.complex()) @@ -350,7 +355,7 @@ def kernel(): @skipIfNvidiaFP64NotInstalled def test_init_from_other_kernel_state_f64(): cudaq.reset_target() - cudaq.set_target('nvidia-fp64') + cudaq.set_target('nvidia', option='fp64') @cudaq.kernel def bell(): diff --git a/runtime/common/ArgumentConversion.cpp b/runtime/common/ArgumentConversion.cpp index b4cbd6671c..e673e9a038 100644 --- a/runtime/common/ArgumentConversion.cpp +++ b/runtime/common/ArgumentConversion.cpp @@ -10,6 +10,7 @@ #include "cudaq.h" #include "cudaq/Optimizer/Builder/Intrinsics.h" #include "cudaq/Optimizer/Builder/Runtime.h" +#include "cudaq/Optimizer/Dialect/Quake/QuakeOps.h" #include "cudaq/Todo.h" #include "cudaq/qis/pauli_word.h" #include "cudaq/utils/registry.h" @@ -132,33 +133,18 @@ static Value genConstant(OpBuilder &builder, const cudaq::state *v, std::string name = kernelName.str() + ".rodata_synth_" + std::to_string(counter++); irBuilder.genVectorOfConstants(loc, substMod, name, vec); - auto conGlobal = builder.create(loc, ptrTy, name); - return builder.create(loc, arrTy, conGlobal); + return builder.create(loc, ptrTy, name); }; - auto conArr = is64Bit ? genConArray.template operator()() + auto buffer = is64Bit ? genConArray.template operator()() : genConArray.template operator()(); - auto createState = is64Bit ? cudaq::createCudaqStateFromDataFP64 - : cudaq::createCudaqStateFromDataFP32; - auto result = irBuilder.loadIntrinsic(substMod, createState); - assert(succeeded(result) && "loading intrinsic should never fail"); - auto arrSize = builder.create(loc, size, 64); auto stateTy = cudaq::cc::StateType::get(ctx); auto statePtrTy = cudaq::cc::PointerType::get(stateTy); - auto i8PtrTy = cudaq::cc::PointerType::get(builder.getI8Type()); - auto buffer = builder.create(loc, arrTy); - builder.create(loc, conArr, buffer); - - auto cast = builder.create(loc, i8PtrTy, buffer); - auto statePtr = builder - .create(loc, statePtrTy, createState, - ValueRange{cast, arrSize}) - .getResult(0); - // TODO: Delete the new state before function exit. - return builder.create(loc, statePtrTy, statePtr); + return builder.create(loc, statePtrTy, buffer, + arrSize); } // The program is executed on quantum hardware, state data is not // available and needs to be regenerated. diff --git a/runtime/common/BaseRemoteRESTQPU.h b/runtime/common/BaseRemoteRESTQPU.h index 853a332551..81d8c5e2b3 100644 --- a/runtime/common/BaseRemoteRESTQPU.h +++ b/runtime/common/BaseRemoteRESTQPU.h @@ -457,6 +457,7 @@ class BaseRemoteRESTQPU : public cudaq::QPU { mlir::SmallVector substs = {substBuff}; pm.addNestedPass( opt::createArgumentSynthesisPass(kernels, substs)); + pm.addPass(opt::createDeleteStates()); } else if (updatedArgs) { cudaq::info("Run Quake Synth.\n"); pm.addPass(cudaq::opt::createQuakeSynthesizer(kernelName, updatedArgs)); diff --git a/runtime/cudaq/builder/kernel_builder.cpp b/runtime/cudaq/builder/kernel_builder.cpp index c1efb7f7fd..6bebbf7278 100644 --- a/runtime/cudaq/builder/kernel_builder.cpp +++ b/runtime/cudaq/builder/kernel_builder.cpp @@ -512,16 +512,11 @@ QuakeValue qalloc(ImplicitLocOpBuilder &builder, QuakeValue &sizeOrVec) { auto eleTy = statePtrTy.getElementType(); if (auto stateTy = dyn_cast(eleTy)) { // get the number of qubits - IRBuilder irBuilder(context); - auto mod = builder.getBlock()->getParentOp()->getParentOfType(); - auto result = irBuilder.loadIntrinsic(mod, getNumQubitsFromCudaqState); - assert(succeeded(result) && "loading intrinsic should never fail"); - auto numQubits = builder.create( - builder.getI64Type(), getNumQubitsFromCudaqState, ValueRange{value}); + auto numQubits = builder.create( + builder.getI64Type(), value); // allocate the number of qubits we need auto veqTy = quake::VeqType::getUnsized(context); - Value qubits = - builder.create(veqTy, numQubits.getResult(0)); + Value qubits = builder.create(veqTy, numQubits); // Add the initialize state op qubits = builder.create(qubits.getType(), qubits, value); diff --git a/runtime/test/test_argument_conversion.cpp b/runtime/test/test_argument_conversion.cpp index 39c0e42f0b..9f936cdcec 100644 --- a/runtime/test/test_argument_conversion.cpp +++ b/runtime/test/test_argument_conversion.cpp @@ -377,16 +377,10 @@ void test_state(mlir::MLIRContext *ctx) { // CHECK-LABEL: cc.arg_subst[0] { // CHECK: %[[VAL_0:.*]] = cc.address_of @[[VAL_GC:.*]] : !cc.ptr x 8>> -// CHECK: %[[VAL_1:.*]] = cc.load %[[VAL_0]] : !cc.ptr x 8>> -// CHECK: %[[VAL_2:.*]] = arith.constant 8 : i64 -// CHECK: %[[VAL_3:.*]] = cc.alloca !cc.array x 8> -// CHECK: cc.store %[[VAL_1]], %[[VAL_3]] : !cc.ptr x 8>> -// CHECK: %[[VAL_4:.*]] = cc.cast %[[VAL_3]] : (!cc.ptr x 8>>) -> !cc.ptr -// CHECK: %[[VAL_5:.*]] = func.call @__nvqpp_cudaq_state_createFromData_fp64(%[[VAL_4]], %[[VAL_2]]) : (!cc.ptr, i64) -> !cc.ptr -// CHECK: %[[VAL_6:.*]] = cc.cast %[[VAL_5]] : (!cc.ptr) -> !cc.ptr +// CHECK: %[[VAL_1:.*]] = arith.constant 8 : i64 +// CHECK: %[[VAL_2:.*]] = quake.create_state %[[VAL_0]], %[[VAL_1]] : (!cc.ptr x 8>>, i64) -> !cc.ptr // CHECK: } // CHECK-DAG: cc.global constant private @[[VAL_GC]] (dense<[(0.70710678118654757,0.000000e+00), (0.70710678118654757,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> -// CHECK-DAG: func.func private @__nvqpp_cudaq_state_createFromData_fp64(!cc.ptr, i64) -> !cc.ptr // clang-format on } @@ -487,16 +481,10 @@ void test_combinations(mlir::MLIRContext *ctx) { // CHECK: } // CHECK-LABEL: cc.arg_subst[1] { // CHECK: %[[VAL_0:.*]] = cc.address_of @[[VAL_GC:.*]] : !cc.ptr x 8>> -// CHECK: %[[VAL_1:.*]] = cc.load %[[VAL_0]] : !cc.ptr x 8>> -// CHECK: %[[VAL_2:.*]] = arith.constant 8 : i64 -// CHECK: %[[VAL_3:.*]] = cc.alloca !cc.array x 8> -// CHECK: cc.store %[[VAL_1]], %[[VAL_3]] : !cc.ptr x 8>> -// CHECK: %[[VAL_4:.*]] = cc.cast %[[VAL_3]] : (!cc.ptr x 8>>) -> !cc.ptr -// CHECK: %[[VAL_5:.*]] = func.call @__nvqpp_cudaq_state_createFromData_fp64(%[[VAL_4]], %[[VAL_2]]) : (!cc.ptr, i64) -> !cc.ptr -// CHECK: %[[VAL_6:.*]] = cc.cast %[[VAL_5]] : (!cc.ptr) -> !cc.ptr +// CHECK: %[[VAL_1:.*]] = arith.constant 8 : i64 +// CHECK: %[[VAL_5:.*]] = quake.create_state %[[VAL_0]], %[[VAL_1]] : (!cc.ptr x 8>>, i64) -> !cc.ptr // CHECK: } // CHECK-DAG: cc.global constant private @[[VAL_GC]] (dense<[(0.70710678118654757,0.000000e+00), (0.70710678118654757,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> -// CHECK-DAG: func.func private @__nvqpp_cudaq_state_createFromData_fp64(!cc.ptr, i64) -> !cc.ptr // CHECK-LABEL: cc.arg_subst[2] { // CHECK: %[[VAL_0:.*]] = cc.alloca !cc.array // CHECK: %[[VAL_1:.*]] = cc.string_literal "XX" : !cc.ptr> diff --git a/test/AST-Quake/qalloc_state.cpp b/test/AST-Quake/qalloc_state.cpp index 44f3132ea9..8ac1d138cb 100644 --- a/test/AST-Quake/qalloc_state.cpp +++ b/test/AST-Quake/qalloc_state.cpp @@ -20,7 +20,7 @@ struct Eins { // CHECK-LABEL: func.func @__nvqpp__mlirgen__Eins( // CHECK-SAME: %[[VAL_0:.*]]: !cc.ptr) -> !cc.stdvec -// CHECK: %[[VAL_3:.*]] = call @__nvqpp_cudaq_state_numberOfQubits(%[[VAL_0]]) : (!cc.ptr) -> i64 +// CHECK: %[[VAL_3:.*]] = quake.get_number_of_qubits %[[VAL_0]] : (!cc.ptr) -> i64 // CHECK: %[[VAL_5:.*]] = quake.alloca !quake.veq[%[[VAL_3]] : i64] // CHECK: %[[VAL_6:.*]] = quake.init_state %[[VAL_5]], %[[VAL_0]] : (!quake.veq, !cc.ptr) -> !quake.veq @@ -34,7 +34,7 @@ struct Zwei { // CHECK-LABEL: func.func @__nvqpp__mlirgen__Zwei( // CHECK-SAME: %[[VAL_0:.*]]: !cc.ptr) -> !cc.stdvec -// CHECK: %[[VAL_3:.*]] = call @__nvqpp_cudaq_state_numberOfQubits(%[[VAL_0]]) : (!cc.ptr) -> i64 +// CHECK: %[[VAL_3:.*]] = quake.get_number_of_qubits %[[VAL_0]] : (!cc.ptr) -> i64 // CHECK: %[[VAL_5:.*]] = quake.alloca !quake.veq[%[[VAL_3]] : i64] // CHECK: %[[VAL_6:.*]] = quake.init_state %[[VAL_5]], %[[VAL_0]] : (!quake.veq, !cc.ptr) -> !quake.veq @@ -48,7 +48,7 @@ struct Drei { // CHECK-LABEL: func.func @__nvqpp__mlirgen__Drei( // CHECK-SAME: %[[VAL_0:.*]]: !cc.ptr) -> !cc.stdvec -// CHECK: %[[VAL_3:.*]] = call @__nvqpp_cudaq_state_numberOfQubits(%[[VAL_0]]) : (!cc.ptr) -> i64 +// CHECK: %[[VAL_3:.*]] = quake.get_number_of_qubits %[[VAL_0]] : (!cc.ptr) -> i64 // CHECK: %[[VAL_5:.*]] = quake.alloca !quake.veq[%[[VAL_3]] : i64] // CHECK: %[[VAL_6:.*]] = quake.init_state %[[VAL_5]], %[[VAL_0]] : (!quake.veq, !cc.ptr) -> !quake.veq @@ -62,8 +62,7 @@ struct Vier { // CHECK-LABEL: func.func @__nvqpp__mlirgen__Vier( // CHECK-SAME: %[[VAL_0:.*]]: !cc.ptr) -> !cc.stdvec -// CHECK: %[[VAL_3:.*]] = call @__nvqpp_cudaq_state_numberOfQubits(%[[VAL_0]]) : (!cc.ptr) -> i64 +// CHECK: %[[VAL_3:.*]] = quake.get_number_of_qubits %[[VAL_0]] : (!cc.ptr) -> i64 // CHECK: %[[VAL_5:.*]] = quake.alloca !quake.veq[%[[VAL_3]] : i64] // CHECK: %[[VAL_6:.*]] = quake.init_state %[[VAL_5]], %[[VAL_0]] : (!quake.veq, !cc.ptr) -> !quake.veq -// CHECK: func.func private @__nvqpp_cudaq_state_numberOfQubits(!cc.ptr) -> i64 diff --git a/test/Quake/delete_states.qke b/test/Quake/delete_states.qke index a2d4a9eb1c..93dd0aa3ae 100644 --- a/test/Quake/delete_states.qke +++ b/test/Quake/delete_states.qke @@ -9,76 +9,56 @@ // RUN: cudaq-opt -delete-states -canonicalize %s | FileCheck %s module { - func.func @__nvqpp__mlirgen__function_test_state_param._Z16test_state_paramPN5cudaq5stateE() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { + func.func @test_state_param() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { %c8_i64 = arith.constant 8 : i64 - %0 = cc.address_of @function_test_state_param._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 : !cc.ptr x 8>> - %1 = cc.load %0 : !cc.ptr x 8>> - %2 = cc.alloca !cc.array x 8> - cc.store %1, %2 : !cc.ptr x 8>> - %3 = cc.cast %2 : (!cc.ptr x 8>>) -> !cc.ptr - %4 = call @__nvqpp_cudaq_state_createFromData_fp32(%3, %c8_i64) : (!cc.ptr, i64) -> !cc.ptr - %5 = call @__nvqpp_cudaq_state_numberOfQubits(%4) : (!cc.ptr) -> i64 - %6 = quake.alloca !quake.veq[%5 : i64] - %7 = quake.init_state %6, %4 : (!quake.veq, !cc.ptr) -> !quake.veq + %0 = cc.address_of @test_state_param.rodata_synth_0 : !cc.ptr x 8>> + %1 = quake.create_state %0, %c8_i64 : (!cc.ptr x 8>>, i64) -> !cc.ptr + %2 = quake.get_number_of_qubits %1 : (!cc.ptr) -> i64 + %3 = quake.alloca !quake.veq[%2 : i64] + %4 = quake.init_state %3, %1 : (!quake.veq, !cc.ptr) -> !quake.veq return } - func.func private @__nvqpp_cudaq_state_numberOfQubits(!cc.ptr) -> i64 - cc.global constant private @function_test_state_param._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00 -,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> - func.func private @__nvqpp_cudaq_state_createFromData_fp32(!cc.ptr, i64) -> !cc.ptr + cc.global constant private @test_state_param.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> -// CHECK-LABEL: func.func @__nvqpp__mlirgen__function_test_state_param._Z16test_state_paramPN5cudaq5stateE() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { -// CHECK: %[[VAL_0:.*]] = cc.address_of @function_test_state_param._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 : !cc.ptr x 8>> -// CHECK: %[[VAL_1:.*]] = cc.load %[[VAL_0]] : !cc.ptr x 8>> -// CHECK: %[[VAL_2:.*]] = cc.alloca !cc.array x 8> -// CHECK: cc.store %[[VAL_1]], %[[VAL_2]] : !cc.ptr x 8>> -// CHECK: %[[VAL_3:.*]] = quake.alloca !quake.veq<3> -// CHECK: %[[VAL_4:.*]] = quake.init_state %[[VAL_3]], %[[VAL_2]] : (!quake.veq<3>, !cc.ptr x 8>>) -> !quake.veq<3> +// CHECK-LABEL: func.func @test_state_param() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { +// CHECK: %[[VAL_0:.*]] = cc.address_of @test_state_param.rodata_synth_0 : !cc.ptr x 8>> +// CHECK: %[[VAL_1:.*]] = quake.alloca !quake.veq<3> +// CHECK: %[[VAL_2:.*]] = quake.init_state %[[VAL_1]], %[[VAL_0]] : (!quake.veq<3>, !cc.ptr x 8>>) -> !quake.veq<3> +// CHECK: return // CHECK: } -// CHECK-DAG: cc.global constant private @function_test_state_param._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> +// CHECK-DAG: cc.global constant private @test_state_param.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> - func.func @__nvqpp__mlirgen__sub_kernel(%arg : !cc.ptr) attributes {"cudaq-kernel", no_this} { - %0 = call @__nvqpp_cudaq_state_numberOfQubits(%arg) : (!cc.ptr) -> i64 + func.func @sub_kernel(%arg : !cc.ptr) attributes {"cudaq-kernel", no_this} { + %0 = quake.get_number_of_qubits %arg : (!cc.ptr) -> i64 %1 = quake.alloca !quake.veq[%0 : i64] %2 = quake.init_state %1, %arg : (!quake.veq, !cc.ptr) -> !quake.veq return } - func.func @__nvqpp__mlirgen__function_test_state_param1._Z16test_state_paramPN5cudaq5stateE() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { + func.func @test_state_param1() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { %c8_i64 = arith.constant 8 : i64 - %0 = cc.address_of @function_test_state_param1._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 : !cc.ptr x 8>> - %1 = cc.load %0 : !cc.ptr x 8>> - %2 = cc.alloca !cc.array x 8> - cc.store %1, %2 : !cc.ptr x 8>> - %3 = cc.cast %2 : (!cc.ptr x 8>>) -> !cc.ptr - %4 = call @__nvqpp_cudaq_state_createFromData_fp32(%3, %c8_i64) : (!cc.ptr, i64) -> !cc.ptr - call @__nvqpp__mlirgen__sub_kernel(%4) : (!cc.ptr) -> () + %0 = cc.address_of @test_state_param1.rodata_synth_0 : !cc.ptr x 8>> + %1 = quake.create_state %0, %c8_i64 : (!cc.ptr x 8>>, i64) -> !cc.ptr + call @sub_kernel(%1) : (!cc.ptr) -> () return } - cc.global constant private @function_test_state_param1._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00 + cc.global constant private @test_state_param1.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00 ,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> -// CHECK: func.func @__nvqpp__mlirgen__sub_kernel(%[[VAL_ARG:.*]]: !cc.ptr) attributes {"cudaq-kernel", no_this} { -// CHECK: %[[VAL_0:.*]] = call @__nvqpp_cudaq_state_numberOfQubits(%[[VAL_ARG]]) : (!cc.ptr) -> i64 +// CHECK: func.func @sub_kernel(%arg0: !cc.ptr) attributes {"cudaq-kernel", no_this} { +// CHECK: %[[VAL_0:.*]] = quake.get_number_of_qubits %arg0 : (!cc.ptr) -> i64 // CHECK: %[[VAL_1:.*]] = quake.alloca !quake.veq[%[[VAL_0]] : i64] -// CHECK: %[[VAL_2:.*]] = quake.init_state %[[VAL_1]], %[[VAL_ARG]] : (!quake.veq, !cc.ptr) -> !quake.veq +// CHECK: %[[VAL_2:.*]] = quake.init_state %[[VAL_1]], %arg0 : (!quake.veq, !cc.ptr) -> !quake.veq // CHECK: return -// CHECK: } - -// CHECK-LABEL: func.func @__nvqpp__mlirgen__function_test_state_param1._Z16test_state_paramPN5cudaq5stateE() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { +// CHECK: } +// CHECK: func.func @test_state_param1() attributes {"cudaq-entrypoint", "cudaq-kernel", no_this} { // CHECK: %[[VAL_0:.*]] = arith.constant 8 : i64 -// CHECK: %[[VAL_1:.*]] = cc.address_of @function_test_state_param1._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 : !cc.ptr x 8>> -// CHECK: %[[VAL_2:.*]] = cc.load %[[VAL_1]] : !cc.ptr x 8>> -// CHECK: %[[VAL_3:.*]] = cc.alloca !cc.array x 8> -// CHECK: cc.store %[[VAL_2]], %[[VAL_3]] : !cc.ptr x 8>> -// CHECK: %[[VAL_4:.*]] = cc.cast %[[VAL_3]] : (!cc.ptr x 8>>) -> !cc.ptr -// CHECK: %[[VAL_5:.*]] = call @__nvqpp_cudaq_state_createFromData_fp32(%[[VAL_4]], %[[VAL_0]]) : (!cc.ptr, i64) -> !cc.ptr -// CHECK: call @__nvqpp__mlirgen__sub_kernel(%[[VAL_5]]) : (!cc.ptr) -> () -// CHECK: call @__nvqpp_cudaq_state_delete(%[[VAL_5]]) : (!cc.ptr) -> () +// CHECK: %[[VAL_1:.*]] = cc.address_of @test_state_param1.rodata_synth_0 : !cc.ptr x 8>> +// CHECK: %[[VAL_2:.*]] = quake.create_state %[[VAL_1]], %[[VAL_0]] : (!cc.ptr x 8>>, i64) -> !cc.ptr +// CHECK: call @sub_kernel(%[[VAL_2]]) : (!cc.ptr) -> () +// CHECK: quake.delete_state %[[VAL_2]] : !cc.ptr // CHECK: return // CHECK: } -// CHECK-DAG: cc.global constant private @function_test_state_param1._Z16test_state_paramPN5cudaq5stateE.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> -// CHECK-DAG: func.func private @__nvqpp_cudaq_state_delete(!cc.ptr) +// CHECK-DAG: cc.global constant private @test_state_param1.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> } - diff --git a/test/Quake/roundtrip-ops.qke b/test/Quake/roundtrip-ops.qke index 5c9f31fae4..3b7088f4dd 100644 --- a/test/Quake/roundtrip-ops.qke +++ b/test/Quake/roundtrip-ops.qke @@ -153,9 +153,23 @@ func.func @quantum_ops() { %48 = cc.string_literal "XXY" : !cc.ptr> quake.exp_pauli %f2, %46, %48 : (f64, !quake.veq<3>, !cc.ptr>) -> () + // State + %i8 = arith.constant 8 : i64 + %49 = cc.address_of @quantum_ops.rodata_synth_0 : !cc.ptr x 8>> + %50 = quake.create_state %49, %i8 : (!cc.ptr x 8>>, i64) -> !cc.ptr + %51 = quake.get_number_of_qubits %50 : (!cc.ptr) -> i64 + %52 = quake.alloca !quake.veq[%51 : i64] + %53 = quake.init_state %52, %50 : (!quake.veq, !cc.ptr) -> !quake.veq + + %54 = quake.create_state %49, %i8 : (!cc.ptr x 8>>, i64) -> !cc.ptr + quake.delete_state %54: !cc.ptr return } +cc.global constant private @quantum_ops.rodata_synth_0 (dense<[(0.707106769,0.000000e+00), (0.707106769,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00,0.000000e+00), (0.000000e+00 +,0.000000e+00), (0.000000e+00,0.000000e+00)]> : tensor<8xcomplex>) : !cc.array x 8> + + // CHECK-LABEL: func.func @quantum_ops() { // CHECK: %[[VAL_0:.*]] = quake.alloca !quake.ref // CHECK: quake.dealloc %[[VAL_0]] : !quake.ref @@ -265,6 +279,14 @@ func.func @quantum_ops() { // CHECK: %[[VAL_59:.*]] = arith.constant 1.200000e+01 : f64 // CHECK: %[[VAL_60:.*]] = cc.string_literal "XXY" : !cc.ptr> // CHECK: quake.exp_pauli %[[VAL_59]], %[[VAL_54]], %[[VAL_60]] : (f64, !quake.veq<3>, !cc.ptr>) -> () +// CHECK: %[[VAL_61:.*]] = arith.constant 8 : i64 +// CHECK: %[[VAL_62:.*]] = cc.address_of @quantum_ops.rodata_synth_0 : !cc.ptr x 8>> +// CHECK: %[[VAL_63:.*]] = quake.create_state %[[VAL_62]], %[[VAL_61]] : (!cc.ptr x 8>>, i64) -> !cc.ptr +// CHECK: %[[VAL_64:.*]] = quake.get_number_of_qubits %[[VAL_63]] : (!cc.ptr) -> i64 +// CHECK: %[[VAL_65:.*]] = quake.alloca !quake.veq[%[[VAL_64]] : i64] +// CHECK: %[[VAL_66:.*]] = quake.init_state %[[VAL_65]], %[[VAL_63]] : (!quake.veq, !cc.ptr) -> !quake.veq +// CHECK: %[[VAL_67:.*]] = quake.create_state %[[VAL_62]], %[[VAL_61]] : (!cc.ptr x 8>>, i64) -> !cc.ptr +// CHECK: quake.delete_state %[[VAL_67]] : !cc.ptr // CHECK: return // CHECK: } From 2137a4a3e516f7afc15e9e1bff9717b266201a96 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Wed, 8 Jan 2025 13:19:47 -0800 Subject: [PATCH 3/4] [C++] Add support for character literals to the C++ bridge. (#2495) Signed-off-by: Eric Schweitz --- include/cudaq/Frontend/nvqpp/ASTBridge.h | 1 + lib/Frontend/nvqpp/ConvertExpr.cpp | 8 +++ test/AST-Quake/character_comparison.cpp | 87 ++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 test/AST-Quake/character_comparison.cpp diff --git a/include/cudaq/Frontend/nvqpp/ASTBridge.h b/include/cudaq/Frontend/nvqpp/ASTBridge.h index 4a4fd43785..67245e594d 100644 --- a/include/cudaq/Frontend/nvqpp/ASTBridge.h +++ b/include/cudaq/Frontend/nvqpp/ASTBridge.h @@ -339,6 +339,7 @@ class QuakeBridgeVisitor bool VisitInitListExpr(clang::InitListExpr *x); bool VisitIntegerLiteral(clang::IntegerLiteral *x); + bool VisitCharacterLiteral(clang::CharacterLiteral *x); bool VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr *x); bool VisitMaterializeTemporaryExpr(clang::MaterializeTemporaryExpr *x); bool VisitUnaryOperator(clang::UnaryOperator *x); diff --git a/lib/Frontend/nvqpp/ConvertExpr.cpp b/lib/Frontend/nvqpp/ConvertExpr.cpp index 5be475ccb7..19f753af1b 100644 --- a/lib/Frontend/nvqpp/ConvertExpr.cpp +++ b/lib/Frontend/nvqpp/ConvertExpr.cpp @@ -499,6 +499,14 @@ bool QuakeBridgeVisitor::VisitIntegerLiteral(clang::IntegerLiteral *x) { return pushValue(getConstantInt(builder, loc, intVal, intTy)); } +bool QuakeBridgeVisitor::VisitCharacterLiteral(clang::CharacterLiteral *x) { + auto loc = toLocation(x->getSourceRange()); + auto intTy = + builtinTypeToType(cast(x->getType().getTypePtr())); + auto intVal = x->getValue(); + return pushValue(builder.create(loc, intVal, intTy)); +} + bool QuakeBridgeVisitor::VisitUnaryOperator(clang::UnaryOperator *x) { auto loc = toLocation(x->getSourceRange()); switch (x->getOpcode()) { diff --git a/test/AST-Quake/character_comparison.cpp b/test/AST-Quake/character_comparison.cpp new file mode 100644 index 0000000000..d6550f1682 --- /dev/null +++ b/test/AST-Quake/character_comparison.cpp @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. * + * All rights reserved. * + * * + * This source code and the accompanying materials are made available under * + * the terms of the Apache License 2.0 which accompanies this distribution. * + ******************************************************************************/ + +// clang-format off +// RUN: cudaq-quake %s | cudaq-opt | FileCheck %s +// clang-format on + +#include "cudaq.h" + +__qpu__ void apply_pauli(cudaq::qview<> qubits, const std::vector &word) { + for (std::size_t i = 0; i < word.size(); i++) { + if (word[i] == 'X') { + x(qubits[i]); + } + if (word[i] == 'Y') { + y(qubits[i]); + } + if (word[i] == 'Z') { + z(qubits[i]); + } + } +} + +// CHECK-LABEL: func.func @__nvqpp__mlirgen__function_apply_pauli +// CHECK-SAME: %[[VAL_0:.*]]: !quake.veq, %[[VAL_1:.*]]: !cc.stdvec) attributes +// CHECK-DAG: %[[VAL_2:.*]] = arith.constant 90 : i32 +// CHECK-DAG: %[[VAL_3:.*]] = arith.constant 89 : i32 +// CHECK-DAG: %[[VAL_4:.*]] = arith.constant 88 : i32 +// CHECK-DAG: %[[VAL_5:.*]] = arith.constant 0 : i64 +// CHECK-DAG: %[[VAL_6:.*]] = arith.constant 1 : i64 +// CHECK: cc.scope { +// CHECK: %[[VAL_7:.*]] = cc.alloca i64 +// CHECK: cc.store %[[VAL_5]], %[[VAL_7]] : !cc.ptr +// CHECK: cc.loop while { +// CHECK: %[[VAL_8:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_9:.*]] = cc.stdvec_size %[[VAL_1]] : (!cc.stdvec) -> i64 +// CHECK: %[[VAL_10:.*]] = arith.cmpi ult, %[[VAL_8]], %[[VAL_9]] : i64 +// CHECK: cc.condition %[[VAL_10]] +// CHECK: } do { +// CHECK: %[[VAL_11:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_12:.*]] = cc.stdvec_data %[[VAL_1]] : (!cc.stdvec) -> !cc.ptr> +// CHECK: %[[VAL_13:.*]] = cc.compute_ptr %[[VAL_12]][%[[VAL_11]]] : (!cc.ptr>, i64) -> !cc.ptr +// CHECK: %[[VAL_14:.*]] = cc.load %[[VAL_13]] : !cc.ptr +// CHECK: %[[VAL_15:.*]] = cc.cast {{.*}}%[[VAL_14]] : (i8) -> i32 +// CHECK: %[[VAL_16:.*]] = arith.cmpi eq, %[[VAL_15]], %[[VAL_4]] : i32 +// CHECK: cc.if(%[[VAL_16]]) { +// CHECK: %[[VAL_17:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_18:.*]] = quake.extract_ref %[[VAL_0]][%[[VAL_17]]] : (!quake.veq, i64) -> !quake.ref +// CHECK: quake.x %[[VAL_18]] : (!quake.ref) -> () +// CHECK: } +// CHECK: %[[VAL_19:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_20:.*]] = cc.stdvec_data %[[VAL_1]] : (!cc.stdvec) -> !cc.ptr> +// CHECK: %[[VAL_21:.*]] = cc.compute_ptr %[[VAL_20]][%[[VAL_19]]] : (!cc.ptr>, i64) -> !cc.ptr +// CHECK: %[[VAL_22:.*]] = cc.load %[[VAL_21]] : !cc.ptr +// CHECK: %[[VAL_23:.*]] = cc.cast {{.*}}%[[VAL_22]] : (i8) -> i32 +// CHECK: %[[VAL_24:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_3]] : i32 +// CHECK: cc.if(%[[VAL_24]]) { +// CHECK: %[[VAL_25:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_26:.*]] = quake.extract_ref %[[VAL_0]][%[[VAL_25]]] : (!quake.veq, i64) -> !quake.ref +// CHECK: quake.y %[[VAL_26]] : (!quake.ref) -> () +// CHECK: } +// CHECK: %[[VAL_27:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_28:.*]] = cc.stdvec_data %[[VAL_1]] : (!cc.stdvec) -> !cc.ptr> +// CHECK: %[[VAL_29:.*]] = cc.compute_ptr %[[VAL_28]][%[[VAL_27]]] : (!cc.ptr>, i64) -> !cc.ptr +// CHECK: %[[VAL_30:.*]] = cc.load %[[VAL_29]] : !cc.ptr +// CHECK: %[[VAL_31:.*]] = cc.cast {{.*}}%[[VAL_30]] : (i8) -> i32 +// CHECK: %[[VAL_32:.*]] = arith.cmpi eq, %[[VAL_31]], %[[VAL_2]] : i32 +// CHECK: cc.if(%[[VAL_32]]) { +// CHECK: %[[VAL_33:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_34:.*]] = quake.extract_ref %[[VAL_0]][%[[VAL_33]]] : (!quake.veq, i64) -> !quake.ref +// CHECK: quake.z %[[VAL_34]] : (!quake.ref) -> () +// CHECK: } +// CHECK: cc.continue +// CHECK: } step { +// CHECK: %[[VAL_35:.*]] = cc.load %[[VAL_7]] : !cc.ptr +// CHECK: %[[VAL_36:.*]] = arith.addi %[[VAL_35]], %[[VAL_6]] : i64 +// CHECK: cc.store %[[VAL_36]], %[[VAL_7]] : !cc.ptr +// CHECK: } +// CHECK: } +// CHECK: return +// CHECK: } + From da44eda8c3798018f90ea300f3a8e1042b939f44 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 8 Jan 2025 15:20:45 -0800 Subject: [PATCH 4/4] Allow mx and my gates in OpenQasm2 translation (#2494) * Allow mx and my gates in OpenQasm2 translation Signed-off-by: Anna Gringauze * Address CR comments Signed-off-by: Anna Gringauze --------- Signed-off-by: Anna Gringauze --- .../cudaq/platform/py_alt_launch_kernel.cpp | 1 + python/tests/backends/test_braket.py | 4 +- .../mlir/test_output_translate_openqasm.py | 174 +++++++++++++++++- .../default/rest/helpers/braket/braket.yml | 2 +- .../rest/helpers/infleqtion/infleqtion.yml | 2 +- 5 files changed, 178 insertions(+), 5 deletions(-) diff --git a/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp b/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp index e095a6d712..3232e26b11 100644 --- a/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp +++ b/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp @@ -667,6 +667,7 @@ std::string getASM(const std::string &name, MlirModule module, "CHToCX", "CCZToCX", "CRzToCX", "CRyToCX", "CRxToCX", "CR1ToCX", "CCZToCX", "RxAdjToRx", "RyAdjToRy", "RzAdjToRz"}})); + pm.addPass(cudaq::opt::createQuakeToCCPrep()); pm.addNestedPass(createCanonicalizerPass()); pm.addNestedPass(cudaq::opt::createExpandControlVeqs()); pm.addNestedPass(cudaq::opt::createCombineQuantumAllocations()); diff --git a/python/tests/backends/test_braket.py b/python/tests/backends/test_braket.py index 8190c29ba3..e847d19714 100644 --- a/python/tests/backends/test_braket.py +++ b/python/tests/backends/test_braket.py @@ -100,8 +100,8 @@ def single_qubit_gates(): rz(np.pi, q) s(q) t(q) - # mx(q) ## Unsupported - # my(q) ## Unsupported + mx(q) + my(q) mz(q) # Test here is that this runs diff --git a/python/tests/mlir/test_output_translate_openqasm.py b/python/tests/mlir/test_output_translate_openqasm.py index 1ea16b276b..4c510ed489 100644 --- a/python/tests/mlir/test_output_translate_openqasm.py +++ b/python/tests/mlir/test_output_translate_openqasm.py @@ -11,7 +11,7 @@ import cudaq -def test_synth_and_openqasm(): +def test_openqasm2_synth(): @cudaq.kernel def ghz(numQubits: int): @@ -35,3 +35,175 @@ def ghz(numQubits: int): # CHECK: cx var0[1], var0[2]; # CHECK: cx var0[2], var0[3]; # CHECK: cx var0[3], var0[4]; + +def test_openqasm2_gates(): + + @cudaq.kernel + def gates(): + q = cudaq.qubit() + ctrl0 = cudaq.qubit() + ctrl1 = cudaq.qubit() + h(q) + x(q) + y(q) + z(q) + s(q) + t(q) + h.ctrl(ctrl0, q) + z.ctrl(ctrl0, ctrl1, q) + rx.ctrl(np.pi, ctrl0, q) + ry.ctrl(np.pi, ctrl0, q) + rz.ctrl(np.pi, ctrl0, q) + r1.ctrl(np.pi, ctrl0, q) + r1(np.pi, q) + rx(np.pi, q) + rx.adj(np.pi, q) + ry(np.pi, q) + ry.adj(np.pi, q) + rz(np.pi, q) + rz.adj(np.pi, q) + mx(q) + my(q) + mz(q) + + print(cudaq.translate(gates, format="openqasm2")) + +# CHECK: // Code generated by NVIDIA's nvq++ compiler +# CHECK: OPENQASM 2.0; + +# CHECK: include "qelib1.inc"; + +# CHECK: qreg var0[3]; +# CHECK: h var0[0]; +# CHECK: x var0[0]; +# CHECK: y var0[0]; +# CHECK: z var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: h var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: h var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[2], var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[2], var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[2], var0[1]; +# CHECK: rz(-7.853982e-01) var0[1]; +# CHECK: rx(1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rx(-1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: cx var0[2], var0[1]; +# CHECK: rz(7.853982e-01) var0[1]; +# CHECK: rx(1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rx(-1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rz(7.853982e-01) var0[2]; +# CHECK: rx(1.570796e+00) var0[2]; +# CHECK: rz(0.000000e+00) var0[2]; +# CHECK: rx(-1.570796e+00) var0[2]; +# CHECK: rz(0.000000e+00) var0[2]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: ry(-1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: ry(1.570796e+00) var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: ry(1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: ry(-1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(1.570796e+00) var0[1]; +# CHECK: rx(1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rx(-1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rz(3.141593e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(3.141593e+00) var0[0]; +# CHECK: rx(-3.141593e+00) var0[0]; +# CHECK: ry(3.141593e+00) var0[0]; +# CHECK: ry(-3.141593e+00) var0[0]; +# CHECK: rz(3.141593e+00) var0[0]; +# CHECK: rz(-3.141593e+00) var0[0]; +# CHECK: h var0[0]; +# CHECK: creg var4[1]; +# CHECK: measure var0[0] -> var4[0]; +# CHECK: sdg var0[0]; +# CHECK: h var0[0]; +# CHECK: creg var5[1]; +# CHECK: measure var0[0] -> var5[0]; +# CHECK: creg var6[1]; +# CHECK: measure var0[0] -> var6[0]; diff --git a/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml b/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml index a382d50adf..04db01abee 100644 --- a/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml +++ b/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml @@ -17,7 +17,7 @@ config: # Tell NVQ++ to generate glue code to set the target backend name gen-target-backend: true # Define the lowering pipeline - platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg,canonicalize,multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,R1ToU3,U3ToRotations,CHToCX,CCZToCX,CRzToCX,CRyToCX,CRxToCX,CR1ToCX,RxAdjToRx,RyAdjToRy,RzAdjToRz},func.func(expand-control-veqs,combine-quantum-alloc,canonicalize,combine-measurements)" + platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg,canonicalize,multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,R1ToU3,U3ToRotations,CHToCX,CCZToCX,CRzToCX,CRyToCX,CRxToCX,CR1ToCX,RxAdjToRx,RyAdjToRy,RzAdjToRz},quake-to-cc-prep,func.func(expand-control-veqs,combine-quantum-alloc,canonicalize,combine-measurements)" # Tell the rest-qpu that we are generating OpenQASM 2.0. codegen-emission: qasm2 # Library mode is only for simulators, physical backends must turn this off diff --git a/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml b/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml index fb22981c82..81d151a6f1 100644 --- a/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml +++ b/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml @@ -17,7 +17,7 @@ config: # Tell NVQ++ to generate glue code to set the target backend name gen-target-backend: true # Define the lowering pipeline - platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg),canonicalize,func.func(multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,CCZToCX,CRyToCX,CRxToCX,R1AdjToR1,RxAdjToRx,RyAdjToRy,RzAdjToRz},func.func(memtoreg{quantum=0}),symbol-dce" + platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg),canonicalize,func.func(multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,CCZToCX,CRyToCX,CRxToCX,R1AdjToR1,RxAdjToRx,RyAdjToRy,RzAdjToRz},quake-to-cc-prep,func.func(memtoreg{quantum=0}),symbol-dce" # Tell the rest-qpu that we are generating OpenQASM 2.0. codegen-emission: qasm2 # Library mode is only for simulators, physical backends must turn this off