@@ -785,7 +785,7 @@ struct TestDetachedSignatureConversion : public ConversionPattern {
785
785
ConversionPatternRewriter &rewriter) const final {
786
786
if (op->getNumRegions () != 1 )
787
787
return failure ();
788
- OperationState state (op->getLoc (), " test.legal_op_with_region " , operands,
788
+ OperationState state (op->getLoc (), " test.legal_op " , operands,
789
789
op->getResultTypes (), {}, BlockRange ());
790
790
Region *newRegion = state.addRegion ();
791
791
rewriter.inlineRegionBefore (op->getRegion (0 ), *newRegion,
@@ -1234,6 +1234,49 @@ class TestRepetitive1ToNConsumer : public ConversionPattern {
1234
1234
}
1235
1235
};
1236
1236
1237
+ // / A pattern that tests two back-to-back 1 -> 2 op replacements.
1238
+ class TestMultiple1ToNReplacement : public ConversionPattern {
1239
+ public:
1240
+ TestMultiple1ToNReplacement (MLIRContext *ctx, const TypeConverter &converter)
1241
+ : ConversionPattern(converter, " test.multiple_1_to_n_replacement" , 1 ,
1242
+ ctx) {}
1243
+ LogicalResult
1244
+ matchAndRewrite (Operation *op, ArrayRef<ValueRange> operands,
1245
+ ConversionPatternRewriter &rewriter) const final {
1246
+ // Helper function that replaces the given op with a new op of the given
1247
+ // name and doubles each result (1 -> 2 replacement of each result).
1248
+ auto replaceWithDoubleResults = [&](Operation *op, StringRef name) {
1249
+ SmallVector<Type> types;
1250
+ for (Type t : op->getResultTypes ()) {
1251
+ types.push_back (t);
1252
+ types.push_back (t);
1253
+ }
1254
+ OperationState state (op->getLoc (), name,
1255
+ /* operands=*/ {}, types, op->getAttrs ());
1256
+ auto *newOp = rewriter.create (state);
1257
+ SmallVector<ValueRange> repls;
1258
+ for (size_t i = 0 , e = op->getNumResults (); i < e; ++i)
1259
+ repls.push_back (newOp->getResults ().slice (2 * i, 2 ));
1260
+ rewriter.replaceOpWithMultiple (op, repls);
1261
+ return newOp;
1262
+ };
1263
+
1264
+ // Replace test.multiple_1_to_n_replacement with test.step_1.
1265
+ Operation *repl1 = replaceWithDoubleResults (op, " test.step_1" );
1266
+ // Now replace test.step_1 with test.legal_op.
1267
+ // TODO: Ideally, it should not be necessary to reset the insertion point
1268
+ // here. Based on the API calls, it looks like test.step_1 is entirely
1269
+ // erased. But that's not the case: an argument materialization will
1270
+ // survive. And that argument materialization will be used by the users of
1271
+ // `op`. If we don't reset the insertion point here, we get dominance
1272
+ // errors. This will be fixed when we have 1:N support in the conversion
1273
+ // value mapping.
1274
+ rewriter.setInsertionPoint (repl1);
1275
+ replaceWithDoubleResults (repl1, " test.legal_op" );
1276
+ return success ();
1277
+ }
1278
+ };
1279
+
1237
1280
} // namespace
1238
1281
1239
1282
namespace {
@@ -1319,7 +1362,8 @@ struct TestLegalizePatternDriver
1319
1362
TestUndoPropertiesModification, TestEraseOp,
1320
1363
TestRepetitive1ToNConsumer>(&getContext ());
1321
1364
patterns.add <TestDropOpSignatureConversion, TestDropAndReplaceInvalidOp,
1322
- TestPassthroughInvalidOp>(&getContext (), converter);
1365
+ TestPassthroughInvalidOp, TestMultiple1ToNReplacement>(
1366
+ &getContext (), converter);
1323
1367
patterns.add <TestDuplicateBlockArgs>(converter, &getContext ());
1324
1368
mlir::populateAnyFunctionOpInterfaceTypeConversionPattern (patterns,
1325
1369
converter);
@@ -1330,8 +1374,7 @@ struct TestLegalizePatternDriver
1330
1374
target.addLegalOp <ModuleOp>();
1331
1375
target.addLegalOp <LegalOpA, LegalOpB, LegalOpC, TestCastOp, TestValidOp,
1332
1376
TerminatorOp, OneRegionOp>();
1333
- target.addLegalOp (
1334
- OperationName (" test.legal_op_with_region" , &getContext ()));
1377
+ target.addLegalOp (OperationName (" test.legal_op" , &getContext ()));
1335
1378
target
1336
1379
.addIllegalOp <ILLegalOpF, TestRegionBuilderOp, TestOpWithRegionFold>();
1337
1380
target.addDynamicallyLegalOp <TestReturnOp>([](TestReturnOp op) {
0 commit comments