From ffbe8ef6d9e9d40d86db7f65746909991aff77a5 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1385694+bcdonovan@users.noreply.github.com> Date: Thu, 2 May 2024 10:03:53 -0400 Subject: [PATCH] [Backport] backport multiple commits to testing branch (#323) Backports: * af612a2 Fix default-only switch statements (#324) * 9613280 remove qubits from SynchronizeOp (#322) --------- Co-authored-by: mbhealy --- include/Dialect/Pulse/Utils/Utils.h | 17 ++++++++++ lib/Conversion/QUIRToPulse/LoadPulseCals.cpp | 5 ++- lib/Conversion/QUIRToPulse/QUIRToPulse.cpp | 13 ++++++-- .../OpenQASM3/QUIRGenQASM3Visitor.cpp | 9 +++--- .../default-only-switch-64bb951256d7d2b5.yaml | 4 +++ .../OpenQASM3/switch-default-only.qasm3 | 32 +++++++++++++++++++ 6 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/default-only-switch-64bb951256d7d2b5.yaml create mode 100644 test/Frontend/OpenQASM3/switch-default-only.qasm3 diff --git a/include/Dialect/Pulse/Utils/Utils.h b/include/Dialect/Pulse/Utils/Utils.h index 2cdea100c..ec2cf8e9e 100644 --- a/include/Dialect/Pulse/Utils/Utils.h +++ b/include/Dialect/Pulse/Utils/Utils.h @@ -82,4 +82,21 @@ MixFrameOp getMixFrameOp(PulseOpTy pulseOp, return mixFrameOp; } +template +llvm::StringRef getMixFrameName(PulseOpTy pulseOp, SequenceOp sequenceOp) { + + auto frameArgIndex = + pulseOp.getTarget().template cast().getArgNumber(); + + assert(sequenceOp->hasAttrOfType("pulse.args") and + "no pulse.args found for the pulse cal sequence."); + + auto argAttr = sequenceOp->getAttrOfType("pulse.args"); + + llvm::StringRef frameName = + argAttr[frameArgIndex].template dyn_cast().getValue(); + + return frameName; +} + } // end namespace mlir::pulse diff --git a/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp b/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp index 0ae5b2fee..e6d7d33b4 100644 --- a/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp +++ b/lib/Conversion/QUIRToPulse/LoadPulseCals.cpp @@ -22,6 +22,7 @@ #include "Dialect/Pulse/IR/PulseDialect.h" #include "Dialect/Pulse/IR/PulseOps.h" +#include "Dialect/QCS/IR/QCSOps.h" #include "Dialect/QUIR/IR/QUIROps.h" #include "Dialect/QUIR/IR/QUIRTraits.h" #include "Dialect/QUIR/Utils/Utils.h" @@ -145,7 +146,9 @@ void LoadPulseCalsPass::loadPulseCals(CallCircuitOp callCircuitOp, loadPulseCals(castOp, callCircuitOp, funcOp); else if (auto castOp = dyn_cast(op)) loadPulseCals(castOp, callCircuitOp, funcOp); - else { + else if (isa(op)) { + // no pulse call to load for a delay cycles op + } else { LLVM_DEBUG(llvm::dbgs() << "no pulse cal loading needed for " << op); assert((!op->hasTrait() and !op->hasTrait()) && diff --git a/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp b/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp index 6bfd4e7b3..b01fd5d9a 100644 --- a/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp +++ b/lib/Conversion/QUIRToPulse/QUIRToPulse.cpp @@ -110,6 +110,11 @@ void QUIRToPulsePass::runOnOperation() { // erase circuit ops moduleOp->walk([&](CircuitOp circOp) { circOp->erase(); }); + // Remove all arguments from synchronization ops + moduleOp->walk([](qcs::SynchronizeOp synchOp) { + synchOp.getQubitsMutable().assign(ValueRange({})); + }); + // erase qubit ops and constant angle ops moduleOp->walk([&](Operation *op) { if (isa(op)) @@ -216,6 +221,11 @@ QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp &callCircuitOp, PulseOpSchedulingInterface::setDuration(pulseCalCallSequenceOp, durValue); } + } else if (isa(quirOp)) { + // a qcs.delay_cycles may be inserted into a quir.circuit and should be + // placed outside of the sequence at the call point + auto *newDelayCyclesOp = builder.clone(*quirOp); + newDelayCyclesOp->moveAfter(callCircuitOp); } else assert(((isa(quirOp) or isa(quirOp) or isa(quirOp))) && @@ -229,7 +239,7 @@ QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp &callCircuitOp, convertedPulseSequenceOpReturnTypes.size())); convertedPulseSequenceOp.setType(newFuncType); entryBuilder.create( - convertedPulseSequenceOp.back().back().getLoc(), + convertedPulseSequenceOp.getLoc(), mlir::ValueRange{convertedPulseSequenceOpReturnValues}); convertedPulseSequenceOp->moveBefore(mainFunc); @@ -239,7 +249,6 @@ QUIRToPulsePass::convertCircuitToSequence(CallCircuitOp &callCircuitOp, convertedPulseSequenceOp, convertedPulseSequenceOpArgs); convertedPulseCallSequenceOp->moveAfter(callCircuitOp); - return convertedPulseCallSequenceOp; } diff --git a/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp b/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp index fe15ba242..bb7f38624 100644 --- a/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp +++ b/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp @@ -540,11 +540,10 @@ void QUIRGenQASM3Visitor::visit(const ASTSwitchStatementNode *node) { SmallVector caseValues; for (auto const &[key, caseStatement] : node->GetCaseStatementsMap()) caseValues.push_back(caseStatement->GetCaseIndex()); - if (!caseValues.empty()) - caseValuesAttr = DenseIntElementsAttr::get( - VectorType::get(static_cast(caseValues.size()), - builder.getIntegerType(32)), - caseValues); + caseValuesAttr = DenseIntElementsAttr::get( + VectorType::get(static_cast(caseValues.size()), + builder.getIntegerType(32)), + caseValues); auto caseOperands = node->GetCaseStatementsMap(); diff --git a/releasenotes/notes/default-only-switch-64bb951256d7d2b5.yaml b/releasenotes/notes/default-only-switch-64bb951256d7d2b5.yaml new file mode 100644 index 000000000..08ea6303e --- /dev/null +++ b/releasenotes/notes/default-only-switch-64bb951256d7d2b5.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - | + Switch statements with only a default region will now correctly compile. diff --git a/test/Frontend/OpenQASM3/switch-default-only.qasm3 b/test/Frontend/OpenQASM3/switch-default-only.qasm3 new file mode 100644 index 000000000..79fa5a729 --- /dev/null +++ b/test/Frontend/OpenQASM3/switch-default-only.qasm3 @@ -0,0 +1,32 @@ +OPENQASM 3.0; +// RUN: qss-compiler -X=qasm --emit=ast-pretty %s | FileCheck %s --match-full-lines --check-prefix AST-PRETTY +// RUN: qss-compiler -X=qasm --emit=mlir %s --enable-circuits-from-qasm=false| FileCheck %s --match-full-lines --check-prefixes MLIR +// RUN: qss-compiler -X=qasm --emit=mlir %s --enable-circuits-from-qasm | FileCheck %s --match-full-lines --check-prefixes MLIR + +// +// This code is part of Qiskit. +// +// (C) Copyright IBM 2023, 2024. +// +// This code is licensed under the Apache License, Version 2.0 with LLVM +// Exceptions. You may obtain a copy of this license in the LICENSE.txt +// file in the root directory of this source tree. +// +// Any modifications or derivative works of this code must retain this +// copyright notice, and modified files need to carry a notice indicating +// that they have been altered from the originals. + +int i = 15; +qubit $0; +// MLIR: quir.switch %{{.*}}{ +// MLIR-NEXT: }[] +// AST-PRETTY: SwitchStatementNode(SwitchQuantity(name=i, type=ASTTypeIdentifier), +switch (i) { + // AST-PRETTY:statements=[ + // AST-PRETTY:], + // AST-PRETTY:default statement=[ + // AST-PRETTY:]) + default: { + } + break; +}