22 for (
const auto &vals : values)
23 llvm::append_range(
result, vals);
30template <
typename SourceOp,
typename ConcretePattern>
31class Structural1ToNConversionPattern :
public OpConversionPattern<SourceOp> {
33 using OpConversionPattern<SourceOp>::typeConverter;
34 using OpConversionPattern<SourceOp>::OpConversionPattern;
35 using OneToNOpAdaptor =
36 typename OpConversionPattern<SourceOp>::OneToNOpAdaptor;
49 matchAndRewrite(SourceOp op, OneToNOpAdaptor adaptor,
50 ConversionPatternRewriter &rewriter)
const override {
51 SmallVector<Type> dstTypes;
52 SmallVector<unsigned> offsets;
55 for (Value v : op.getResults()) {
56 if (
failed(typeConverter->convertType(v, dstTypes)))
57 return rewriter.notifyMatchFailure(op,
"could not convert result type");
58 offsets.push_back(dstTypes.size());
62 std::optional<SourceOp> newOp =
63 static_cast<const ConcretePattern *
>(
this)->convertSourceOp(
64 op, adaptor, rewriter, dstTypes);
67 return rewriter.notifyMatchFailure(op,
"could not convert operation");
70 SmallVector<ValueRange> packedRets;
71 for (
unsigned i = 1, e = offsets.size(); i < e; i++) {
72 unsigned start = offsets[i - 1], end = offsets[i];
73 unsigned len = end - start;
74 ValueRange mappedValue = newOp->getResults().slice(start, len);
75 packedRets.push_back(mappedValue);
78 rewriter.replaceOpWithMultiple(op, packedRets);
83class ConvertForOpTypes
84 :
public Structural1ToNConversionPattern<ForOp, ConvertForOpTypes> {
86 using Structural1ToNConversionPattern::Structural1ToNConversionPattern;
89 std::optional<ForOp> convertSourceOp(ForOp op, OneToNOpAdaptor adaptor,
90 ConversionPatternRewriter &rewriter,
110 if (
failed(rewriter.convertRegionTypes(&op.getRegion(), *typeConverter)))
115 ForOp newOp = ForOp::create(rewriter, op.getLoc(),
116 llvm::getSingleElement(adaptor.getLowerBound()),
117 llvm::getSingleElement(adaptor.getUpperBound()),
118 llvm::getSingleElement(adaptor.getStep()),
120 nullptr, op.getUnsignedCmp());
123 newOp->setAttrs(op->getAttrs());
126 rewriter.eraseBlock(newOp.getBody(0));
128 rewriter.inlineRegionBefore(op.getRegion(), newOp.getRegion(),
129 newOp.getRegion().end());
136class ConvertIfOpTypes
137 :
public Structural1ToNConversionPattern<IfOp, ConvertIfOpTypes> {
139 using Structural1ToNConversionPattern::Structural1ToNConversionPattern;
141 std::optional<IfOp> convertSourceOp(IfOp op, OneToNOpAdaptor adaptor,
142 ConversionPatternRewriter &rewriter,
146 IfOp::create(rewriter, op.getLoc(), dstTypes,
147 llvm::getSingleElement(adaptor.getCondition()),
true);
148 newOp->setAttrs(op->getAttrs());
151 rewriter.eraseBlock(newOp.elseBlock());
152 rewriter.eraseBlock(newOp.thenBlock());
155 rewriter.inlineRegionBefore(op.getThenRegion(), newOp.getThenRegion(),
156 newOp.getThenRegion().end());
157 rewriter.inlineRegionBefore(op.getElseRegion(), newOp.getElseRegion(),
158 newOp.getElseRegion().end());
166class ConvertWhileOpTypes
167 :
public Structural1ToNConversionPattern<WhileOp, ConvertWhileOpTypes> {
169 using Structural1ToNConversionPattern::Structural1ToNConversionPattern;
171 std::optional<WhileOp> convertSourceOp(WhileOp op, OneToNOpAdaptor adaptor,
172 ConversionPatternRewriter &rewriter,
174 auto newOp = WhileOp::create(rewriter, op.getLoc(), dstTypes,
177 for (
auto i : {0u, 1u}) {
178 if (
failed(rewriter.convertRegionTypes(&op.getRegion(i), *typeConverter)))
180 auto &dstRegion = newOp.getRegion(i);
181 rewriter.inlineRegionBefore(op.getRegion(i), dstRegion, dstRegion.end());
189class ConvertIndexSwitchOpTypes
190 :
public Structural1ToNConversionPattern<IndexSwitchOp,
191 ConvertIndexSwitchOpTypes> {
193 using Structural1ToNConversionPattern::Structural1ToNConversionPattern;
195 std::optional<IndexSwitchOp>
196 convertSourceOp(IndexSwitchOp op, OneToNOpAdaptor adaptor,
197 ConversionPatternRewriter &rewriter,
200 IndexSwitchOp::create(rewriter, op.getLoc(), dstTypes, op.getArg(),
201 op.getCases(), op.getNumCases());
203 for (
unsigned i = 0u; i < op.getNumRegions(); i++) {
204 auto &dstRegion = newOp.getRegion(i);
205 rewriter.inlineRegionBefore(op.getRegion(i), dstRegion, dstRegion.end());
216class ConvertYieldOpTypes :
public OpConversionPattern<scf::YieldOp> {
218 using OpConversionPattern::OpConversionPattern;
220 matchAndRewrite(scf::YieldOp op, OneToNOpAdaptor adaptor,
221 ConversionPatternRewriter &rewriter)
const override {
222 rewriter.replaceOpWithNewOp<scf::YieldOp>(
230class ConvertConditionOpTypes :
public OpConversionPattern<ConditionOp> {
232 using OpConversionPattern<ConditionOp>::OpConversionPattern;
234 matchAndRewrite(ConditionOp op, OneToNOpAdaptor adaptor,
235 ConversionPatternRewriter &rewriter)
const override {
236 rewriter.modifyOpInPlace(
237 op, [&]() { op->setOperands(
flattenValues(adaptor.getOperands())); });
246 patterns.add<ConvertForOpTypes, ConvertIfOpTypes, ConvertYieldOpTypes,
247 ConvertWhileOpTypes, ConvertConditionOpTypes,
248 ConvertIndexSwitchOpTypes>(typeConverter,
patterns.getContext(),
254 target.addDynamicallyLegalOp<ForOp, IfOp, IndexSwitchOp>(
255 [&](
Operation *op) {
return typeConverter.isLegal(op->getResults()); });
256 target.addDynamicallyLegalOp<scf::YieldOp>([&](scf::YieldOp op) {
259 if (!isa<ForOp, IfOp, WhileOp, IndexSwitchOp>(op->getParentOp()))
261 return typeConverter.isLegal(op.getOperands());
263 target.addDynamicallyLegalOp<WhileOp, ConditionOp>(
264 [&](
Operation *op) {
return typeConverter.isLegal(op); });
static SmallVector< Value > flattenValues(ArrayRef< ValueRange > values)
Flatten the given value ranges into a single vector of values.
Operation is the basic unit of execution within MLIR.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
void populateSCFStructuralTypeConversions(const TypeConverter &typeConverter, RewritePatternSet &patterns, PatternBenefit benefit=1)
Similar to populateSCFStructuralTypeConversionsAndLegality but does not populate the conversion targe...
void populateSCFStructuralTypeConversionsAndLegality(const TypeConverter &typeConverter, RewritePatternSet &patterns, ConversionTarget &target, PatternBenefit benefit=1)
Populates patterns for SCF structural type conversions and sets up the provided ConversionTarget with...
void populateSCFStructuralTypeConversionTarget(const TypeConverter &typeConverter, ConversionTarget &target)
Updates the ConversionTarget with dynamic legality of SCF operations based on the provided type conve...
Include the generated interface declarations.
const FrozenRewritePatternSet & patterns