diff --git a/mlir/include/mlir/Compiler/CompilerPipeline.h b/mlir/include/mlir/Compiler/CompilerPipeline.h index 54d9f039de..a53ebef0a2 100644 --- a/mlir/include/mlir/Compiler/CompilerPipeline.h +++ b/mlir/include/mlir/Compiler/CompilerPipeline.h @@ -49,6 +49,9 @@ struct QuantumCompilerConfig { /// Enable Hadamard lifting bool enableHadamardLifting = false; + + /// (TODO:) Pointer to a QDMI device + void* device = nullptr; }; /** @@ -66,6 +69,8 @@ struct CompilationRecord { std::string afterQCOCanon; std::string afterOptimization; std::string afterOptimizationCanon; + std::string afterTranspilation; + std::string afterTranspilationCanon; std::string afterQCConversion; std::string afterQCCanon; std::string afterQIRConversion; @@ -86,10 +91,12 @@ struct CompilationRecord { * 4. QCO cleanup pipeline * 5. Quantum optimization passes * 6. QCO cleanup pipeline - * 7. QC dialect - converted back for backend lowering - * 8. QC cleanup pipeline - * 9. QIR (Quantum Intermediate Representation) - optional final lowering - * 10. QIR cleanup pipeline + * 7. Quantum transpilation passes - optional fit to hardware constraints + * 8. QCO cleanup pipeline + * 9. QC dialect - converted back for backend lowering + * 10. QC cleanup pipeline + * 11. QIR (Quantum Intermediate Representation) - optional final lowering + * 12. QIR cleanup pipeline * * Following MLIR best practices, simplification and dead-value cleanup are * run after each major transformation stage. diff --git a/mlir/lib/Compiler/CompilerPipeline.cpp b/mlir/lib/Compiler/CompilerPipeline.cpp index b3f6b9daef..35b4d4842b 100644 --- a/mlir/lib/Compiler/CompilerPipeline.cpp +++ b/mlir/lib/Compiler/CompilerPipeline.cpp @@ -171,11 +171,44 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module, if (record != nullptr && config_.recordIntermediates) { record->afterOptimizationCanon = captureIR(module); if (config_.printIRAfterAllStages) { - prettyPrintStage(module, "Final QCO Cleanup", ++currentStage, + prettyPrintStage(module, "Post-Optimization QCO Cleanup", ++currentStage, totalStages); } } - // Stage 7: QCO-to-QC conversion + // Stage 7: Transpilation passes (optional) + if (config_.device != nullptr) { + if (failed(runStage([&](PassManager& pm) { + /// TODO: + // Individual passes use the device handle to query properties. + // if (device.hasCouplingMap()) + // pm.addPass(createMappingPass(config_.device)) + // } + // pm.addPass(createNativeGateDecompositionPass(config_.device)) + }))) { + return failure(); + } + if (record != nullptr && config_.recordIntermediates) { + record->afterTranspilation = captureIR(module); + if (config_.printIRAfterAllStages) { + prettyPrintStage(module, "Transpilation Passes", ++currentStage, + totalStages); + } + } + // Stage 8: QCO cleanup (optional) + if (failed(runStage( + [&](PassManager& pm) { populateQCOCleanupPipeline(pm); }))) { + return failure(); + } + if (record != nullptr && config_.recordIntermediates) { + record->afterTranspilationCanon = captureIR(module); + if (config_.printIRAfterAllStages) { + prettyPrintStage(module, "Post-Transpilation QCO Cleanup", + ++currentStage, totalStages); + } + } + } + + // Stage 9: QCO-to-QC conversion if (failed(runStage([&](PassManager& pm) { pm.addPass(createQCOToQC()); }))) { return failure(); } @@ -186,7 +219,7 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module, totalStages); } } - // Stage 8: QC cleanup + // Stage 10: QC cleanup if (failed( runStage([&](PassManager& pm) { populateQCCleanupPipeline(pm); }))) { return failure(); @@ -218,7 +251,7 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module, totalStages); } } - // Stage 10: QIR cleanup (optional) + // Stage 12: QIR cleanup (optional) if (failed(runStage( [&](PassManager& pm) { populateQIRCleanupPipeline(pm); }))) { return failure(); diff --git a/mlir/tools/mqt-cc/mqt-cc.cpp b/mlir/tools/mqt-cc/mqt-cc.cpp index cc13e2cdba..b3f1137d75 100644 --- a/mlir/tools/mqt-cc/mqt-cc.cpp +++ b/mlir/tools/mqt-cc/mqt-cc.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -91,6 +92,10 @@ static llvm::cl::opt enableHadamardLifting( llvm::cl::desc("Apply Hadamard lifting during optimization"), llvm::cl::init(false)); +static llvm::cl::opt> + arch("arch", llvm::cl::desc("Specify the target architecture"), + llvm::cl::init(std::nullopt)); + /** * @brief Load and parse a .qasm file */ @@ -188,6 +193,18 @@ int main(int argc, char** argv) { disableMergeSingleQubitRotationGates; config.enableHadamardLifting = enableHadamardLifting; + if (arch != std::nullopt) { + /// TODO: + // 1) Load the dynamic device libraries with the given name + // e.g. _device.dylib + // or raise error if the library is not found. + // 2) Set the device handle in the QuantumCompilerConfig + // Individual passes use the device handle to query properties. + // + // Also: Make sure that everything still works if the arch options isn't + // supplied. + } + // Run the compilation pipeline CompilationRecord record; if (const QuantumCompilerPipeline pipeline(config);