282 lines
12 KiB
C++
282 lines
12 KiB
C++
//===- DialectConversion.h - MLIR dialect conversion pass -------*- C++ -*-===//
|
|
//
|
|
// Copyright 2019 The MLIR Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// =============================================================================
|
|
//
|
|
// This file declares a generic pass for converting between MLIR dialects.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_TRANSFORMS_DIALECTCONVERSION_H_
|
|
#define MLIR_TRANSFORMS_DIALECTCONVERSION_H_
|
|
|
|
#include "mlir/IR/PatternMatch.h"
|
|
#include "mlir/Support/LLVM.h"
|
|
#include "mlir/Support/LogicalResult.h"
|
|
#include "llvm/ADT/MapVector.h"
|
|
|
|
namespace mlir {
|
|
|
|
// Forward declarations.
|
|
class Block;
|
|
class MLIRContext;
|
|
class Operation;
|
|
class Type;
|
|
class Value;
|
|
|
|
/// Base class for the conversion patterns that require type changes. Specific
|
|
/// conversions must derive this class and implement least one `rewrite` method.
|
|
/// NOTE: These conversion patterns can only be used with the 'apply*' methods
|
|
/// below.
|
|
class ConversionPattern : public RewritePattern {
|
|
public:
|
|
/// Construct an ConversionPattern. `rootName` must correspond to the
|
|
/// canonical name of the first operation matched by the pattern.
|
|
ConversionPattern(StringRef rootName, PatternBenefit benefit,
|
|
MLIRContext *ctx)
|
|
: RewritePattern(rootName, benefit, ctx) {}
|
|
|
|
/// Hook for derived classes to implement rewriting. `op` is the (first)
|
|
/// operation matched by the pattern, `operands` is a list of rewritten values
|
|
/// that are passed to this operation, `rewriter` can be used to emit the new
|
|
/// operations. This function must be reimplemented if the
|
|
/// ConversionPattern ever needs to replace an operation that does not
|
|
/// have successors. This function should not fail. If some specific cases of
|
|
/// the operation are not supported, these cases should not be matched.
|
|
virtual void rewrite(Operation *op, ArrayRef<Value *> operands,
|
|
PatternRewriter &rewriter) const {
|
|
llvm_unreachable("unimplemented rewrite");
|
|
}
|
|
|
|
/// Hook for derived classes to implement rewriting. `op` is the (first)
|
|
/// operation matched by the pattern, `properOperands` is a list of rewritten
|
|
/// values that are passed to the operation itself, `destinations` is a list
|
|
/// of (potentially rewritten) successor blocks, `operands` is a list of lists
|
|
/// of rewritten values passed to each of the successors, co-indexed with
|
|
/// `destinations`, `rewriter` can be used to emit the new operations. It must
|
|
/// be reimplemented if the ConversionPattern ever needs to replace a
|
|
/// terminator operation that has successors. This function should not fail
|
|
/// the pass. If some specific cases of the operation are not supported,
|
|
/// these cases should not be matched.
|
|
virtual void rewrite(Operation *op, ArrayRef<Value *> properOperands,
|
|
ArrayRef<Block *> destinations,
|
|
ArrayRef<ArrayRef<Value *>> operands,
|
|
PatternRewriter &rewriter) const {
|
|
llvm_unreachable("unimplemented rewrite for terminators");
|
|
}
|
|
|
|
/// Hook for derived classes to implement combined matching and rewriting.
|
|
virtual PatternMatchResult
|
|
matchAndRewrite(Operation *op, ArrayRef<Value *> properOperands,
|
|
ArrayRef<Block *> destinations,
|
|
ArrayRef<ArrayRef<Value *>> operands,
|
|
PatternRewriter &rewriter) const {
|
|
if (!match(op))
|
|
return matchFailure();
|
|
rewrite(op, properOperands, destinations, operands, rewriter);
|
|
return matchSuccess();
|
|
}
|
|
|
|
/// Hook for derived classes to implement combined matching and rewriting.
|
|
virtual PatternMatchResult matchAndRewrite(Operation *op,
|
|
ArrayRef<Value *> operands,
|
|
PatternRewriter &rewriter) const {
|
|
if (!match(op))
|
|
return matchFailure();
|
|
rewrite(op, operands, rewriter);
|
|
return matchSuccess();
|
|
}
|
|
|
|
/// Attempt to match and rewrite the IR root at the specified operation.
|
|
PatternMatchResult matchAndRewrite(Operation *op,
|
|
PatternRewriter &rewriter) const final;
|
|
|
|
private:
|
|
using RewritePattern::rewrite;
|
|
};
|
|
|
|
/// Base class for type conversion interface. Specific converters must
|
|
/// derive this class and implement the pure virtual functions.
|
|
class TypeConverter {
|
|
public:
|
|
virtual ~TypeConverter() = default;
|
|
|
|
/// Derived classes must reimplement this hook if they need to convert
|
|
/// block or function argument types or function result types. If the target
|
|
/// dialect has support for custom first-class function types, convertType
|
|
/// should create those types for arguments of MLIR function type. It can be
|
|
/// used for values (constant, operands, results) of function type but not for
|
|
/// the function signatures. For the latter, convertFunctionSignatureType is
|
|
/// used instead.
|
|
///
|
|
/// For block attribute types, this function will be called for each attribute
|
|
/// individually.
|
|
///
|
|
/// If type conversion can fail, this function should return a
|
|
/// default-constructed Type. The failure will be then propagated to trigger
|
|
/// the pass failure.
|
|
virtual Type convertType(Type t) { return t; }
|
|
|
|
/// Derived classes must reimplement this hook if they need to change the
|
|
/// function signature during conversion. This function will be called on
|
|
/// a function type corresponding to a function signature and must produce the
|
|
/// converted MLIR function type.
|
|
///
|
|
/// Note: even if some target dialects have first-class function types, they
|
|
/// cannot be used at the top level of MLIR function signature.
|
|
///
|
|
/// The default behavior of this function is to call convertType on individual
|
|
/// function operands and results, and then create a new MLIR function type
|
|
/// from those.
|
|
///
|
|
/// Post-condition: if the returned optional attribute list does not have
|
|
/// a value then no argument attribute conversion happened.
|
|
virtual FunctionType convertFunctionSignatureType(
|
|
FunctionType t, ArrayRef<NamedAttributeList> argAttrs,
|
|
SmallVectorImpl<NamedAttributeList> &convertedArgAttrs);
|
|
};
|
|
|
|
/// This class describes a specific conversion target.
|
|
class ConversionTarget {
|
|
public:
|
|
/// This enumeration corresponds to the specific action to take when
|
|
/// considering an operation legal for this conversion target.
|
|
enum class LegalizationAction {
|
|
/// The target supports this operation.
|
|
Legal,
|
|
|
|
/// This operation has dynamic legalization constraints that must be checked
|
|
/// by the target.
|
|
Dynamic
|
|
};
|
|
|
|
/// The type used to store operation legality information.
|
|
using LegalityMapTy = llvm::MapVector<OperationName, LegalizationAction>;
|
|
|
|
ConversionTarget(MLIRContext &ctx) : ctx(ctx) {}
|
|
virtual ~ConversionTarget() = default;
|
|
|
|
/// Runs a custom legalization query for the given operation. This should
|
|
/// return true if the given operation is legal, otherwise false.
|
|
virtual bool isLegal(Operation *op) const {
|
|
llvm_unreachable(
|
|
"targets with custom legalization must override 'isLegal'");
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Legality Registration
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Register a legality action for the given operation.
|
|
void setOpAction(OperationName op, LegalizationAction action);
|
|
template <typename OpT> void setOpAction(LegalizationAction action) {
|
|
setOpAction(OperationName(OpT::getOperationName(), &ctx), action);
|
|
}
|
|
|
|
/// Register the given operations as legal.
|
|
template <typename OpT> void addLegalOp() {
|
|
setOpAction<OpT>(LegalizationAction::Legal);
|
|
}
|
|
template <typename OpT, typename OpT2, typename... OpTs> void addLegalOp() {
|
|
addLegalOp<OpT>();
|
|
addLegalOp<OpT2, OpTs...>();
|
|
}
|
|
|
|
/// Register the given operation as dynamically legal, i.e. requiring custom
|
|
/// handling by the target via 'isLegal'.
|
|
template <typename OpT> void addDynamicallyLegalOp() {
|
|
setOpAction<OpT>(LegalizationAction::Dynamic);
|
|
}
|
|
template <typename OpT, typename OpT2, typename... OpTs>
|
|
void addDynamicallyLegalOp() {
|
|
addDynamicallyLegalOp<OpT>();
|
|
addDynamicallyLegalOp<OpT2, OpTs...>();
|
|
}
|
|
|
|
/// Register a legality action for the given dialects.
|
|
void setDialectAction(ArrayRef<StringRef> dialectNames,
|
|
LegalizationAction action);
|
|
|
|
/// Register the operations of the given dialects as legal.
|
|
template <typename... Names>
|
|
void addLegalDialect(StringRef name, Names... names) {
|
|
SmallVector<StringRef, 2> dialectNames({name, names...});
|
|
setDialectAction(dialectNames, LegalizationAction::Legal);
|
|
}
|
|
template <typename... Args> void addLegalDialect() {
|
|
SmallVector<StringRef, 2> dialectNames({Args::getDialectNamespace()...});
|
|
setDialectAction(dialectNames, LegalizationAction::Legal);
|
|
}
|
|
|
|
/// Register the operations of the given dialects as dynamically legal, i.e.
|
|
/// requiring custom handling by the target via 'isLegal'.
|
|
template <typename... Names>
|
|
void addDynamicallyLegalDialect(StringRef name, Names... names) {
|
|
SmallVector<StringRef, 2> dialectNames({name, names...});
|
|
setDialectAction(dialectNames, LegalizationAction::Dynamic);
|
|
}
|
|
template <typename... Args> void addDynamicallyLegalDialect() {
|
|
SmallVector<StringRef, 2> dialectNames({Args::getDialectNamespace()...});
|
|
setDialectAction(dialectNames, LegalizationAction::Dynamic);
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Legality Querying
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Get the legality action for the given operation.
|
|
llvm::Optional<LegalizationAction> getOpAction(OperationName op) const;
|
|
|
|
private:
|
|
/// A deterministic mapping of operation name to the specific legality action
|
|
/// to take.
|
|
LegalityMapTy legalOperations;
|
|
|
|
/// A deterministic mapping of dialect name to the specific legality action to
|
|
/// take.
|
|
llvm::StringMap<LegalizationAction> legalDialects;
|
|
|
|
/// The current context this target applies to.
|
|
MLIRContext &ctx;
|
|
};
|
|
|
|
/// Convert the given module with the provided conversion patterns and type
|
|
/// conversion object. If conversion fails for specific functions, those
|
|
/// functions remains unmodified.
|
|
LLVM_NODISCARD LogicalResult applyConversionPatterns(
|
|
Module &module, ConversionTarget &target, TypeConverter &converter,
|
|
OwningRewritePatternList &&patterns);
|
|
|
|
/// Convert the given functions with the provided conversion patterns. This will
|
|
/// convert as many of the operations within each function as possible given the
|
|
/// set of patterns. If conversion fails for specific functions, those functions
|
|
/// remains unmodified.
|
|
LLVM_NODISCARD
|
|
LogicalResult applyConversionPatterns(ArrayRef<Function *> fns,
|
|
ConversionTarget &target,
|
|
TypeConverter &converter,
|
|
OwningRewritePatternList &&patterns);
|
|
|
|
/// Convert the given function with the provided conversion patterns. This will
|
|
/// convert as many of the operations within 'fn' as possible given the set of
|
|
/// patterns.
|
|
LLVM_NODISCARD
|
|
LogicalResult applyConversionPatterns(Function &fn, ConversionTarget &target,
|
|
OwningRewritePatternList &&patterns);
|
|
|
|
} // end namespace mlir
|
|
|
|
#endif // MLIR_TRANSFORMS_DIALECTCONVERSION_H_
|