@@ -81,6 +81,44 @@ struct MoveCtrlOutside final : OpRewritePattern<InvOp> {
8181 }
8282};
8383
84+ /* *
85+ * @brief Reorder inv around pow, i.e., `inv(pow(p, g)) => pow(p, inv(g))`.
86+ */
87+ struct MovePowOutside final : OpRewritePattern<InvOp> {
88+ using OpRewritePattern::OpRewritePattern;
89+
90+ LogicalResult matchAndRewrite (InvOp invOp,
91+ PatternRewriter& rewriter) const override {
92+ auto innerPow =
93+ llvm::dyn_cast<PowOp>(invOp.getBodyUnitary ().getOperation ());
94+ if (!innerPow) {
95+ return failure ();
96+ }
97+
98+ const double exponent = innerPow.getExponentValue ();
99+
100+ rewriter.replaceOpWithNewOp <PowOp>(
101+ invOp, invOp.getQubitsIn (), exponent,
102+ [&](ValueRange powArgs) -> llvm::SmallVector<Value> {
103+ return InvOp::create (
104+ rewriter, invOp.getLoc (), powArgs,
105+ [&](ValueRange invArgs) -> llvm::SmallVector<Value> {
106+ IRMapping mapping;
107+ auto * innerBody = innerPow.getBody ();
108+ for (size_t i = 0 ; i < innerPow.getNumTargets (); ++i) {
109+ mapping.map (innerBody->getArgument (i), invArgs[i]);
110+ }
111+ return rewriter
112+ .clone (*innerPow.getBodyUnitary ().getOperation (),
113+ mapping)
114+ ->getResults ();
115+ })
116+ .getResults ();
117+ });
118+ return success ();
119+ }
120+ };
121+
84122/* *
85123 * @brief Remove inverse modifiers around self-adjoint gates.
86124 *
@@ -401,8 +439,8 @@ LogicalResult InvOp::verify() {
401439
402440void InvOp::getCanonicalizationPatterns (RewritePatternSet& results,
403441 MLIRContext* context) {
404- results.add <MoveCtrlOutside, InlineSelfAdjoint, ReplaceWithKnownGates ,
405- CancelNestedInv>(context);
442+ results.add <MoveCtrlOutside, MovePowOutside, InlineSelfAdjoint ,
443+ ReplaceWithKnownGates, CancelNestedInv>(context);
406444}
407445
408446std::optional<Eigen::MatrixXcd> InvOp::getUnitaryMatrix () {
0 commit comments