Loading mlir/parsers/qasm3/tests/test_optimization.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,30 @@ cx q[0], q[1]; EXPECT_TRUE(llvm.find("__quantum__qis") == std::string::npos); } TEST(qasm3PassManagerTester, checkResetSimplification) { const std::string src = R"#(OPENQASM 3; include "qelib1.inc"; qubit q[2]; reset q[0]; x q[1]; reset q[0]; )#"; auto llvm = qcor::mlir_compile(src, "test_kernel", qcor::OutputType::LLVMIR, false); std::cout << "LLVM:\n" << llvm << "\n"; // Get the main kernel section only llvm = llvm.substr(llvm.find("@__internal_mlir_test_kernel")); const auto last = llvm.find_first_of("}"); llvm = llvm.substr(0, last + 1); std::cout << "LLVM:\n" << llvm << "\n"; // One reset and one X: EXPECT_EQ(countSubstring(llvm, "__quantum__qis"), 2); EXPECT_EQ(countSubstring(llvm, "__quantum__qis__x"), 1); EXPECT_EQ(countSubstring(llvm, "__quantum__qis__reset"), 1); } TEST(qasm3PassManagerTester, checkRotationMerge) { const std::string src = R"#(OPENQASM 3; include "qelib1.inc"; Loading mlir/transforms/optimizations/IdentityPairRemovalPass.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -130,4 +130,47 @@ void CNOTIdentityPairRemovalPass::runOnOperation() { op.erase(); } } void DuplicateResetRemovalPass::getDependentDialects( DialectRegistry ®istry) const { registry.insert<LLVM::LLVMDialect>(); } void DuplicateResetRemovalPass::runOnOperation() { // Walk the operations within the function. std::vector<mlir::quantum::ValueSemanticsInstOp> deadOps; getOperation().walk([&](mlir::quantum::ValueSemanticsInstOp op) { if (std::find(deadOps.begin(), deadOps.end(), op) != deadOps.end()) { // Skip this op since it was deleted (forward search) return; } auto inst_name = op.name(); if (inst_name != "reset") { return; } auto return_value = *op.result().begin(); if (return_value.hasOneUse()) { // get that one user auto user = *return_value.user_begin(); // cast to a inst op if (auto next_inst = dyn_cast_or_null<mlir::quantum::ValueSemanticsInstOp>(user)) { if (next_inst.name().str() == "reset") { // Two resets in a row: // Chain the input -> output and mark this second reset to delete: (*next_inst.result_begin()) .replaceAllUsesWith(next_inst.getOperand(0)); deadOps.emplace_back(next_inst); } } } }); for (auto &op : deadOps) { op->dropAllUses(); op.erase(); } } } // namespace qcor mlir/transforms/optimizations/IdentityPairRemovalPass.hpp +9 −0 Original line number Diff line number Diff line Loading @@ -29,4 +29,13 @@ struct CNOTIdentityPairRemovalPass void runOnOperation() final; CNOTIdentityPairRemovalPass() {} }; // Remove duplicate reset: // 2 consecutive resets on a single qubit line => remove one. struct DuplicateResetRemovalPass : public PassWrapper<DuplicateResetRemovalPass, OperationPass<ModuleOp>> { void getDependentDialects(DialectRegistry ®istry) const override; void runOnOperation() final; DuplicateResetRemovalPass() {} }; } // namespace qcor No newline at end of file mlir/transforms/pass_manager.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ void configureOptimizationPasses(mlir::PassManager &passManager) { // Simple Identity pair removals passManager.addPass(std::make_unique<SingleQubitIdentityPairRemovalPass>()); passManager.addPass(std::make_unique<CNOTIdentityPairRemovalPass>()); passManager.addPass(std::make_unique<DuplicateResetRemovalPass>()); // Rotation merging passManager.addPass(std::make_unique<RotationMergingPass>()); Loading Loading
mlir/parsers/qasm3/tests/test_optimization.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,30 @@ cx q[0], q[1]; EXPECT_TRUE(llvm.find("__quantum__qis") == std::string::npos); } TEST(qasm3PassManagerTester, checkResetSimplification) { const std::string src = R"#(OPENQASM 3; include "qelib1.inc"; qubit q[2]; reset q[0]; x q[1]; reset q[0]; )#"; auto llvm = qcor::mlir_compile(src, "test_kernel", qcor::OutputType::LLVMIR, false); std::cout << "LLVM:\n" << llvm << "\n"; // Get the main kernel section only llvm = llvm.substr(llvm.find("@__internal_mlir_test_kernel")); const auto last = llvm.find_first_of("}"); llvm = llvm.substr(0, last + 1); std::cout << "LLVM:\n" << llvm << "\n"; // One reset and one X: EXPECT_EQ(countSubstring(llvm, "__quantum__qis"), 2); EXPECT_EQ(countSubstring(llvm, "__quantum__qis__x"), 1); EXPECT_EQ(countSubstring(llvm, "__quantum__qis__reset"), 1); } TEST(qasm3PassManagerTester, checkRotationMerge) { const std::string src = R"#(OPENQASM 3; include "qelib1.inc"; Loading
mlir/transforms/optimizations/IdentityPairRemovalPass.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -130,4 +130,47 @@ void CNOTIdentityPairRemovalPass::runOnOperation() { op.erase(); } } void DuplicateResetRemovalPass::getDependentDialects( DialectRegistry ®istry) const { registry.insert<LLVM::LLVMDialect>(); } void DuplicateResetRemovalPass::runOnOperation() { // Walk the operations within the function. std::vector<mlir::quantum::ValueSemanticsInstOp> deadOps; getOperation().walk([&](mlir::quantum::ValueSemanticsInstOp op) { if (std::find(deadOps.begin(), deadOps.end(), op) != deadOps.end()) { // Skip this op since it was deleted (forward search) return; } auto inst_name = op.name(); if (inst_name != "reset") { return; } auto return_value = *op.result().begin(); if (return_value.hasOneUse()) { // get that one user auto user = *return_value.user_begin(); // cast to a inst op if (auto next_inst = dyn_cast_or_null<mlir::quantum::ValueSemanticsInstOp>(user)) { if (next_inst.name().str() == "reset") { // Two resets in a row: // Chain the input -> output and mark this second reset to delete: (*next_inst.result_begin()) .replaceAllUsesWith(next_inst.getOperand(0)); deadOps.emplace_back(next_inst); } } } }); for (auto &op : deadOps) { op->dropAllUses(); op.erase(); } } } // namespace qcor
mlir/transforms/optimizations/IdentityPairRemovalPass.hpp +9 −0 Original line number Diff line number Diff line Loading @@ -29,4 +29,13 @@ struct CNOTIdentityPairRemovalPass void runOnOperation() final; CNOTIdentityPairRemovalPass() {} }; // Remove duplicate reset: // 2 consecutive resets on a single qubit line => remove one. struct DuplicateResetRemovalPass : public PassWrapper<DuplicateResetRemovalPass, OperationPass<ModuleOp>> { void getDependentDialects(DialectRegistry ®istry) const override; void runOnOperation() final; DuplicateResetRemovalPass() {} }; } // namespace qcor No newline at end of file
mlir/transforms/pass_manager.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ void configureOptimizationPasses(mlir::PassManager &passManager) { // Simple Identity pair removals passManager.addPass(std::make_unique<SingleQubitIdentityPairRemovalPass>()); passManager.addPass(std::make_unique<CNOTIdentityPairRemovalPass>()); passManager.addPass(std::make_unique<DuplicateResetRemovalPass>()); // Rotation merging passManager.addPass(std::make_unique<RotationMergingPass>()); Loading