31#include <mlir/Dialect/SCF/Transforms/Patterns.h>
32#include <mlir/IR/Attributes.h>
33#include <mlir/IR/BuiltinAttributes.h>
34#include <mlir/IR/BuiltinTypes.h>
35#include <mlir/IR/MLIRContext.h>
36#include <mlir/IR/Operation.h>
37#include <mlir/IR/PatternMatch.h>
38#include <mlir/Transforms/DialectConversion.h>
40#include <llvm/ADT/ArrayRef.h>
41#include <llvm/ADT/STLExtras.h>
42#include <llvm/ADT/SmallVector.h>
43#include <llvm/Support/Casting.h>
54 if (!tyConv.isLegal(op)) {
59 mlir::DictionaryAttr dictAttr = op->getAttrDictionary();
60 for (mlir::NamedAttribute n : dictAttr.getValue()) {
61 if (mlir::TypeAttr tyAttr = llvm::dyn_cast<mlir::TypeAttr>(n.getValue())) {
62 mlir::Type t = tyAttr.getValue();
63 if (mlir::FunctionType funcTy = llvm::dyn_cast<mlir::FunctionType>(t)) {
64 if (!tyConv.isSignatureLegal(funcTy)) {
68 if (!tyConv.isLegal(t)) {
113 using NoGeneralBuilder = std::tuple<function::CallOp, array::CreateArrayOp, pod::NewPodOp>;
121class ExecuteRegionTypeConversionPattern
122 :
public mlir::OpConversionPattern<mlir::scf::ExecuteRegionOp> {
124 using OpConversionPattern::OpConversionPattern;
126 mlir::LogicalResult matchAndRewrite(
127 mlir::scf::ExecuteRegionOp op, OneToNOpAdaptor, mlir::ConversionPatternRewriter &rewriter
129 mlir::SmallVector<mlir::Type> newResultTypes;
130 mlir::SmallVector<unsigned> resultOffsets {0};
131 for (mlir::Type resultType : op.getResultTypes()) {
132 if (mlir::failed(getTypeConverter()->convertTypes(resultType, newResultTypes))) {
133 return rewriter.notifyMatchFailure(op,
"could not convert result type");
135 resultOffsets.push_back(newResultTypes.size());
138 if (mlir::failed(rewriter.convertRegionTypes(&op.getRegion(), *getTypeConverter()))) {
139 return rewriter.notifyMatchFailure(op,
"could not convert region types");
142 auto newOp = mlir::scf::ExecuteRegionOp::create(rewriter, op.getLoc(), newResultTypes);
143 newOp->setAttrs(op->getAttrs());
144 rewriter.inlineRegionBefore(op.getRegion(), newOp.getRegion(), newOp.getRegion().end());
146 mlir::SmallVector<mlir::ValueRange> replacements;
147 replacements.reserve(op.getNumResults());
148 for (
unsigned i = 0; i < op.getNumResults(); ++i) {
149 replacements.push_back(
150 newOp.getResults().slice(resultOffsets[i], resultOffsets[i + 1] - resultOffsets[i])
153 rewriter.replaceOpWithMultiple(op, replacements);
154 return mlir::success();
164template <
typename OpClass>
165class GeneralTypeReplacePattern :
public mlir::OpConversionPattern<OpClass> {
169 GeneralTypeReplacePattern(mlir::TypeConverter &converter, mlir::MLIRContext *ctx)
170 :
mlir::OpConversionPattern<OpClass>(converter, ctx, 0) {}
172 mlir::LogicalResult matchAndRewrite(
173 OpClass op,
typename OpClass::Adaptor adaptor, mlir::ConversionPatternRewriter &rewriter
175 const mlir::TypeConverter *converter = mlir::OpConversionPattern<OpClass>::getTypeConverter();
178 mlir::SmallVector<mlir::Type> newResultTypes;
179 if (mlir::failed(converter->convertTypes(op->getResultTypes(), newResultTypes))) {
180 return op->emitError(
"Could not convert Op result types.");
185 adaptor.getAttributes().empty() ||
187 adaptor.getAttributes(), [d = op->getAttrDictionary()](mlir::NamedAttribute a) {
188 return d.contains(a.getName());
193 mlir::SmallVector<mlir::NamedAttribute> newAttrs(op->getAttrDictionary().getValue());
194 for (mlir::NamedAttribute &n : newAttrs) {
195 if (mlir::TypeAttr t = llvm::dyn_cast<mlir::TypeAttr>(n.getValue())) {
196 if (mlir::Type newType = converter->convertType(t.getValue())) {
197 n.setValue(mlir::TypeAttr::get(newType));
199 return op->emitError().append(
"Could not convert type in attribute: ", t);
205 rewriter, op, mlir::TypeRange(newResultTypes), adaptor.getOperands(),
206 mlir::ArrayRef(newAttrs)
208 return mlir::success();
213class CreateArrayOpClassReplacePattern :
public mlir::OpConversionPattern<array::CreateArrayOp> {
217 CreateArrayOpClassReplacePattern(mlir::TypeConverter &converter, mlir::MLIRContext *ctx)
218 : mlir::OpConversionPattern<array::CreateArrayOp>(converter, ctx, 0) {}
220 mlir::LogicalResult matchAndRewrite(
221 array::CreateArrayOp op, OpAdaptor adapter, mlir::ConversionPatternRewriter &rewriter
223 mlir::Type newType = getTypeConverter()->convertType(op.getType());
225 return op->emitError(
"Could not convert Op result type.");
227 assert(llvm::isa<array::ArrayType>(newType) &&
"CreateArrayOp must produce ArrayType result");
228 mlir::DenseI32ArrayAttr numDimsPerMap = op.getNumDimsPerMapAttr();
231 rewriter, op, llvm::cast<array::ArrayType>(newType), adapter.getElements()
235 rewriter, op, llvm::cast<array::ArrayType>(newType), adapter.getMapOperands(),
239 return mlir::success();
244class CallOpClassReplacePattern :
public mlir::OpConversionPattern<function::CallOp> {
246 CallOpClassReplacePattern(mlir::TypeConverter &converter, mlir::MLIRContext *ctx)
247 : mlir::OpConversionPattern<function::CallOp>(converter, ctx, 0) {}
249 mlir::LogicalResult matchAndRewrite(
250 function::CallOp op, OpAdaptor adapter, mlir::ConversionPatternRewriter &rewriter
252 mlir::SmallVector<mlir::Type> newResultTypes;
253 if (mlir::failed(getTypeConverter()->convertTypes(op.getResultTypes(), newResultTypes))) {
254 return op->emitError(
"Could not convert Op result types.");
257 rewriter, op, newResultTypes, op.getCalleeAttr(), adapter.getMapOperands(),
258 op.getNumDimsPerMapAttr(), adapter.getArgOperands()
260 return mlir::success();
265class NewPodOpClassReplacePattern :
public mlir::OpConversionPattern<pod::NewPodOp> {
267 NewPodOpClassReplacePattern(mlir::TypeConverter &converter, mlir::MLIRContext *ctx)
268 : mlir::OpConversionPattern<pod::NewPodOp>(converter, ctx, 0) {}
270 mlir::LogicalResult matchAndRewrite(
271 pod::NewPodOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter
273 auto newResultType = dyn_cast_if_present<pod::PodType>(
274 getTypeConverter()->convertType(op.getResult().getType())
276 if (!newResultType) {
277 return op->emitError(
"Could not convert Op result types.");
280 rewriter, op, newResultType, adaptor.getMapOperands(), op.getNumDimsPerMapAttr(),
283 return mlir::success();
287template <
typename I,
typename NextOpClass,
typename... OtherOpClasses>
288inline void applyToMoreTypes(I inserter) {
289 std::apply(inserter, std::tuple<NextOpClass, OtherOpClasses...> {});
291template <
typename I>
inline void applyToMoreTypes(I) {}
299template <
typename... AdditionalOpClasses>
301 mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, mlir::ConversionTarget &target
303 mlir::RewritePatternSet patterns(ctx);
304 auto inserter = [&](
auto... opClasses) {
305 patterns.add<GeneralTypeReplacePattern<
decltype(opClasses)>...>(tyConv, ctx);
308 applyToMoreTypes<
decltype(inserter), AdditionalOpClasses...>(inserter);
311 CreateArrayOpClassReplacePattern, CallOpClassReplacePattern, NewPodOpClassReplacePattern>(
315 mlir::populateFunctionOpInterfaceTypeConversionPattern<function::FuncDefOp>(patterns, tyConv);
316 mlir::scf::populateSCFStructuralTypeConversionsAndLegality(tyConv, patterns, target);
317 patterns.add<ExecuteRegionTypeConversionPattern>(tyConv, ctx);
318 target.addDynamicallyLegalOp<mlir::scf::ExecuteRegionOp>([&](mlir::scf::ExecuteRegionOp op) {
319 return tyConv.isLegal(op.getResultTypes());
321 target.addDynamicallyLegalOp<mlir::scf::YieldOp>([&](mlir::scf::YieldOp op) {
322 mlir::Operation *parent = op->getParentOp();
324 mlir::scf::ExecuteRegionOp, mlir::scf::ForOp, mlir::scf::IfOp, mlir::scf::WhileOp>(
329 return tyConv.isLegal(op.getOperandTypes());
SmallVector< RecordValue > getInitializedRecordValues(ValueRange initialValues, ArrayAttr initializedRecords)
OpClass replaceOpWithNewOp(Rewriter &rewriter, mlir::Operation *op, Args &&...args)
Wrapper for RewriterBase::replaceOpWithNewOp() that automatically copies discardable attributes (i....
bool isNullOrEmpty(mlir::ArrayAttr a)
mlir::RewritePatternSet newGeneralRewritePatternSet(mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, mlir::ConversionTarget &target)
Return a new RewritePatternSet covering all LLZK op types that may contain a StructType.
bool defaultLegalityCheck(const mlir::TypeConverter &tyConv, mlir::Operation *op)
Check whether an op is legal with respect to the given type converter, including TypeAttr attributes ...
Lists all LLZK op classes that may contain a StructType in their results or attributes.
std::tuple< function::CallOp, array::CreateArrayOp, pod::NewPodOp > NoGeneralBuilder
Ops in this subset do NOT define the general builder function (see above), so they cannot use General...
std::tuple< array::ArrayLengthOp, array::ReadArrayOp, array::WriteArrayOp, array::InsertArrayOp, array::ExtractArrayOp, constrain::EmitEqualityOp, constrain::EmitContainmentOp, component::MemberDefOp, component::MemberReadOp, component::MemberWriteOp, component::CreateStructOp, function::FuncDefOp, function::ReturnOp, global::GlobalDefOp, global::GlobalReadOp, global::GlobalWriteOp, llzk::NonDetOp, pod::ReadPodOp, pod::WritePodOp, polymorphic::UnifiableCastOp, polymorphic::ConstReadOp > WithGeneralBuilder
Ops in this subset define the general builder function: build(OpBuilder&, OperationState&,...