diff --git a/doc/releases/changelog-0.14.0.md b/doc/releases/changelog-0.14.0.md
index a344c0af85..384a8483c8 100644
--- a/doc/releases/changelog-0.14.0.md
+++ b/doc/releases/changelog-0.14.0.md
@@ -650,6 +650,9 @@
* Adding the measurement type into the MLIR assembly format for `qec.ppm` and `qec.select.ppm`
[(#2347)](https://github.com/PennyLaneAI/catalyst/pull/2347)
+* Remove duplicate code for canonicalization and verification of Pauli Product Rotation operations.
+ [(#2313)](https://github.com/PennyLaneAI/catalyst/pull/2313)
+
Documentation 📝
* A new statevector simulator ``lightning.amdgpu`` has been added for optimized performance on AMD GPUs.
diff --git a/mlir/lib/QEC/IR/QECOps.cpp b/mlir/lib/QEC/IR/QECOps.cpp
index 691e05f7f1..d3c1383e8a 100644
--- a/mlir/lib/QEC/IR/QECOps.cpp
+++ b/mlir/lib/QEC/IR/QECOps.cpp
@@ -35,37 +35,45 @@ using namespace catalyst::qec;
#include "QEC/IR/QECOps.cpp.inc"
//===----------------------------------------------------------------------===//
-// QEC op verifiers.
+// QEC op canonicalizers/verifiers helper methods.
//===----------------------------------------------------------------------===//
-LogicalResult PPRotationOp::verify()
+template LogicalResult canonicalizePPROp(OpType op, PatternRewriter &rewriter)
{
- size_t numPauliProduct = getPauliProduct().size();
-
- if (numPauliProduct == 0) {
- return emitOpError("Pauli string must be non-empty");
- }
+ bool allIdentity = llvm::all_of(op.getPauliProduct(), [](mlir::Attribute attr) {
+ auto pauliStr = llvm::cast(attr);
+ return pauliStr.getValue() == "I";
+ });
- if (numPauliProduct != getInQubits().size()) {
- return emitOpError("Number of qubits must match number of pauli operators");
+ if (allIdentity) {
+ rewriter.replaceOp(op, op.getInQubits());
+ return mlir::success();
}
- return mlir::success();
+ return mlir::failure();
}
-LogicalResult PPRotationArbitraryOp::verify()
+template LogicalResult verifyPPROp(OpType op)
{
- size_t numPauliProduct = getPauliProduct().size();
+ size_t numPauliProduct = op.getPauliProduct().size();
if (numPauliProduct == 0) {
- return emitOpError("Pauli string must be non-empty");
+ return op.emitOpError("Pauli string must be non-empty");
}
- if (numPauliProduct != getInQubits().size()) {
- return emitOpError("Number of qubits must match number of pauli operators");
+ if (numPauliProduct != op.getInQubits().size()) {
+ return op.emitOpError("Number of qubits must match number of pauli operators");
}
return mlir::success();
}
+//===----------------------------------------------------------------------===//
+// QEC op verifiers.
+//===----------------------------------------------------------------------===//
+
+LogicalResult PPRotationOp::verify() { return verifyPPROp(*this); }
+
+LogicalResult PPRotationArbitraryOp::verify() { return verifyPPROp(*this); }
+
LogicalResult PPMeasurementOp::verify()
{
if (getInQubits().size() != getPauliProduct().size()) {
@@ -105,35 +113,13 @@ LogicalResult FabricateOp::verify()
LogicalResult PPRotationOp::canonicalize(PPRotationOp op, PatternRewriter &rewriter)
{
- auto pauliProduct = op.getPauliProduct();
-
- bool allIdentity = llvm::all_of(pauliProduct, [](mlir::Attribute attr) {
- auto pauliStr = llvm::cast(attr);
- return pauliStr.getValue() == "I";
- });
-
- if (allIdentity) {
- rewriter.replaceOp(op, op.getInQubits());
- return mlir::success();
- }
- return mlir::failure();
+ return canonicalizePPROp(op, rewriter);
}
LogicalResult PPRotationArbitraryOp::canonicalize(PPRotationArbitraryOp op,
PatternRewriter &rewriter)
{
- auto pauliProduct = op.getPauliProduct();
-
- bool allIdentity = llvm::all_of(pauliProduct, [](mlir::Attribute attr) {
- auto pauliStr = llvm::cast(attr);
- return pauliStr.getValue() == "I";
- });
-
- if (allIdentity) {
- rewriter.replaceOp(op, op.getInQubits());
- return mlir::success();
- }
- return mlir::failure();
+ return canonicalizePPROp(op, rewriter);
}
void LayerOp::build(OpBuilder &builder, OperationState &result, ValueRange inValues,