//===- HomomorphismSimplification.h -----------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef MLIR_TRANSFORMS_SIMPLIFY_HOMOMORPHISM_H_ #define MLIR_TRANSFORMS_SIMPLIFY_HOMOMORPHISM_H_ #include "mlir/IR/IRMapping.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/Value.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include #include #include #include namespace mlir { // If `h` is an homomorphism with respect to the source algebraic structure // induced by function `s` and the target algebraic structure induced by // function `t`, transforms `s(h(x1), h(x2) ..., h(xn))` into // `h(t(x1, x2, ..., xn))`. // // Functors: // --------- // `GetHomomorphismOpOperandFn`: `(Operation*) -> OpOperand*` // Returns the operand relevant to the homomorphism. // There may be other operands that are not relevant. // // `GetHomomorphismOpResultFn`: `(Operation*) -> OpResult` // Returns the result relevant to the homomorphism. // // `GetSourceAlgebraicOpOperandsFn`: `(Operation*, SmallVector&) -> // void` Populates into the vector the operands relevant to the homomorphism. // // `GetSourceAlgebraicOpResultFn`: `(Operation*) -> OpResult` // Return the result of the source algebraic operation relevant to the // homomorphism. // // `GetTargetAlgebraicOpResultFn`: `(Operation*) -> OpResult` // Return the result of the target algebraic operation relevant to the // homomorphism. // // `IsHomomorphismOpFn`: `(Operation*, std::optional) -> bool` // Check if the operation is an homomorphism of the required type. // Additionally if the optional is present checks if the operations are // compatible homomorphisms. // // `IsSourceAlgebraicOpFn`: `(Operation*) -> bool` // Check if the operation is an operation of the algebraic structure. // // `CreateTargetAlgebraicOpFn`: `(Operation*, IRMapping& operandsRemapping, // PatternRewriter &rewriter) -> Operation*` template struct HomomorphismSimplification : public RewritePattern { template HomomorphismSimplification( GetHomomorphismOpOperandFnArg &&getHomomorphismOpOperand, GetHomomorphismOpResultFnArg &&getHomomorphismOpResult, GetSourceAlgebraicOpOperandsFnArg &&getSourceAlgebraicOpOperands, GetSourceAlgebraicOpResultFnArg &&getSourceAlgebraicOpResult, GetTargetAlgebraicOpResultFnArg &&getTargetAlgebraicOpResult, IsHomomorphismOpFnArg &&isHomomorphismOp, IsSourceAlgebraicOpFnArg &&isSourceAlgebraicOp, CreateTargetAlgebraicOpFnArg &&createTargetAlgebraicOpFn, RewritePatternArgs &&...args) : RewritePattern(std::forward(args)...), getHomomorphismOpOperand(std::forward( getHomomorphismOpOperand)), getHomomorphismOpResult(std::forward( getHomomorphismOpResult)), getSourceAlgebraicOpOperands( std::forward( getSourceAlgebraicOpOperands)), getSourceAlgebraicOpResult( std::forward( getSourceAlgebraicOpResult)), getTargetAlgebraicOpResult( std::forward( getTargetAlgebraicOpResult)), isHomomorphismOp(std::forward(isHomomorphismOp)), isSourceAlgebraicOp( std::forward(isSourceAlgebraicOp)), createTargetAlgebraicOpFn(std::forward( createTargetAlgebraicOpFn)) {} LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter) const override { SmallVector algebraicOpOperands; if (failed(matchOp(op, algebraicOpOperands))) { return failure(); } return rewriteOp(op, algebraicOpOperands, rewriter); } private: LogicalResult matchOp(Operation *sourceAlgebraicOp, SmallVector &sourceAlgebraicOpOperands) const { if (!isSourceAlgebraicOp(sourceAlgebraicOp)) { return failure(); } sourceAlgebraicOpOperands.clear(); getSourceAlgebraicOpOperands(sourceAlgebraicOp, sourceAlgebraicOpOperands); if (sourceAlgebraicOpOperands.empty()) { return failure(); } Operation *firstHomomorphismOp = sourceAlgebraicOpOperands.front()->get().getDefiningOp(); if (!firstHomomorphismOp || !isHomomorphismOp(firstHomomorphismOp, std::nullopt)) { return failure(); } OpResult firstHomomorphismOpResult = getHomomorphismOpResult(firstHomomorphismOp); if (firstHomomorphismOpResult != sourceAlgebraicOpOperands.front()->get()) { return failure(); } for (auto operand : sourceAlgebraicOpOperands) { Operation *homomorphismOp = operand->get().getDefiningOp(); if (!homomorphismOp || !isHomomorphismOp(homomorphismOp, firstHomomorphismOp)) { return failure(); } } return success(); } LogicalResult rewriteOp(Operation *sourceAlgebraicOp, const SmallVector &sourceAlgebraicOpOperands, PatternRewriter &rewriter) const { IRMapping irMapping; for (auto operand : sourceAlgebraicOpOperands) { Operation *homomorphismOp = operand->get().getDefiningOp(); irMapping.map(operand->get(), getHomomorphismOpOperand(homomorphismOp)->get()); } Operation *targetAlgebraicOp = createTargetAlgebraicOpFn(sourceAlgebraicOp, irMapping, rewriter); irMapping.clear(); assert(!sourceAlgebraicOpOperands.empty()); Operation *firstHomomorphismOp = sourceAlgebraicOpOperands[0]->get().getDefiningOp(); irMapping.map(getHomomorphismOpOperand(firstHomomorphismOp)->get(), getTargetAlgebraicOpResult(targetAlgebraicOp)); Operation *newHomomorphismOp = rewriter.clone(*firstHomomorphismOp, irMapping); rewriter.replaceAllUsesWith(getSourceAlgebraicOpResult(sourceAlgebraicOp), getHomomorphismOpResult(newHomomorphismOp)); return success(); } GetHomomorphismOpOperandFn getHomomorphismOpOperand; GetHomomorphismOpResultFn getHomomorphismOpResult; GetSourceAlgebraicOpOperandsFn getSourceAlgebraicOpOperands; GetSourceAlgebraicOpResultFn getSourceAlgebraicOpResult; GetTargetAlgebraicOpResultFn getTargetAlgebraicOpResult; IsHomomorphismOpFn isHomomorphismOp; IsSourceAlgebraicOpFn isSourceAlgebraicOp; CreateTargetAlgebraicOpFn createTargetAlgebraicOpFn; }; } // namespace mlir #endif // MLIR_TRANSFORMS_SIMPLIFY_HOMOMORPHISM_H_