28static FailureOr<Block *> getConvertedBlock(ConversionPatternRewriter &rewriter,
32 assert(converter &&
"expected non-null type converter");
33 assert(!block->
isEntryBlock() &&
"entry blocks have no predecessors");
40 std::optional<TypeConverter::SignatureConversion> conversion =
41 converter->convertBlockSignature(block);
43 return rewriter.notifyMatchFailure(branchOp,
44 "could not compute block signature");
45 if (expectedTypes != conversion->getConvertedTypes())
46 return rewriter.notifyMatchFailure(
48 "mismatch between adaptor operand types and computed block signature");
49 return rewriter.applySignatureConversion(block, *conversion, converter);
56 llvm::append_range(
result, vals);
62struct BranchOpConversion :
public OpConversionPattern<cf::BranchOp> {
63 using OpConversionPattern<cf::BranchOp>::OpConversionPattern;
66 matchAndRewrite(cf::BranchOp op, OneToNOpAdaptor adaptor,
67 ConversionPatternRewriter &rewriter)
const override {
68 SmallVector<Value> flattenedAdaptor =
flattenValues(adaptor.getOperands());
69 FailureOr<Block *> convertedBlock =
70 getConvertedBlock(rewriter, getTypeConverter(), op, op.getSuccessor(),
72 if (
failed(convertedBlock))
74 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, flattenedAdaptor,
82struct CondBranchOpConversion :
public OpConversionPattern<cf::CondBranchOp> {
83 using OpConversionPattern<cf::CondBranchOp>::OpConversionPattern;
86 matchAndRewrite(cf::CondBranchOp op, OneToNOpAdaptor adaptor,
87 ConversionPatternRewriter &rewriter)
const override {
88 SmallVector<Value> flattenedAdaptorTrue =
90 SmallVector<Value> flattenedAdaptorFalse =
92 if (!llvm::hasSingleElement(adaptor.getCondition()))
93 return rewriter.notifyMatchFailure(op,
94 "expected single element condition");
95 FailureOr<Block *> convertedTrueBlock =
96 getConvertedBlock(rewriter, getTypeConverter(), op, op.getTrueDest(),
98 if (
failed(convertedTrueBlock))
100 FailureOr<Block *> convertedFalseBlock =
101 getConvertedBlock(rewriter, getTypeConverter(), op, op.getFalseDest(),
103 if (
failed(convertedFalseBlock))
105 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
106 op, llvm::getSingleElement(adaptor.getCondition()),
107 flattenedAdaptorTrue, flattenedAdaptorFalse, op.getBranchWeightsAttr(),
108 *convertedTrueBlock, *convertedFalseBlock);
115struct SwitchOpConversion :
public OpConversionPattern<cf::SwitchOp> {
116 using OpConversionPattern<cf::SwitchOp>::OpConversionPattern;
119 matchAndRewrite(cf::SwitchOp op, OpAdaptor adaptor,
120 ConversionPatternRewriter &rewriter)
const override {
122 FailureOr<Block *> convertedDefaultBlock = getConvertedBlock(
123 rewriter, getTypeConverter(), op, op.getDefaultDestination(),
124 TypeRange(adaptor.getDefaultOperands()));
125 if (
failed(convertedDefaultBlock))
129 SmallVector<Block *> caseDestinations;
130 SmallVector<ValueRange> caseOperands = adaptor.getCaseOperands();
131 for (
auto it : llvm::enumerate(op.getCaseDestinations())) {
133 FailureOr<Block *> convertedBlock =
134 getConvertedBlock(rewriter, getTypeConverter(), op,
b,
136 if (
failed(convertedBlock))
138 caseDestinations.push_back(*convertedBlock);
141 rewriter.replaceOpWithNewOp<cf::SwitchOp>(
142 op, adaptor.getFlag(), *convertedDefaultBlock,
143 adaptor.getDefaultOperands(), adaptor.getCaseValuesAttr(),
144 caseDestinations, caseOperands);
154 patterns.add<BranchOpConversion, CondBranchOpConversion, SwitchOpConversion>(
155 typeConverter,
patterns.getContext(), benefit);
160 target.addDynamicallyLegalOp<cf::BranchOp, cf::CondBranchOp, cf::SwitchOp>(
161 [&](
Operation *op) {
return typeConverter.isLegal(op->getOperands()); });
static SmallVector< Value > flattenValues(ArrayRef< ValueRange > values)
Flatten the given value ranges into a single vector of values.
Block represents an ordered list of Operations.
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
bool isEntryBlock()
Return if this block is the entry block in the parent region.
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...
This class provides an abstraction over the various different ranges of value types.
This class provides an abstraction over the different types of ranges over Values.
void populateCFStructuralTypeConversionTarget(const TypeConverter &typeConverter, ConversionTarget &target)
Updates the ConversionTarget with dynamic legality of CF operations based on the provided type conver...
void populateCFStructuralTypeConversions(const TypeConverter &typeConverter, RewritePatternSet &patterns, PatternBenefit benefit=1)
Similar to populateCFStructuralTypeConversionsAndLegality but does not populate the conversion target...
void populateCFStructuralTypeConversionsAndLegality(const TypeConverter &typeConverter, RewritePatternSet &patterns, ConversionTarget &target, PatternBenefit benefit=1)
Populates patterns for CF structural type conversions and sets up the provided ConversionTarget with ...
Include the generated interface declarations.
const FrozenRewritePatternSet & patterns