26 #define GEN_PASS_DEF_SCFTOEMITC
27 #include "mlir/Conversion/Passes.h.inc"
41 void populateConvertToEmitCConversionPatterns(
52 dialect->addInterfaces<SCFToEmitCDialectInterface>();
58 struct SCFToEmitCPass :
public impl::SCFToEmitCBase<SCFToEmitCPass> {
59 void runOnOperation()
override;
68 matchAndRewrite(ForOp forOp, OpAdaptor adaptor,
75 createVariablesForResults(T op,
const TypeConverter *typeConverter,
78 if (!op.getNumResults())
87 for (
OpResult result : op.getResults()) {
93 emitc::VariableOp var =
94 emitc::VariableOp::create(rewriter, loc, varType, noInit);
95 resultVariables.push_back(var);
105 for (
auto [value, var] : llvm::zip(values, variables))
106 emitc::AssignOp::create(rewriter, loc, var, value);
111 return llvm::map_to_vector<>(variables, [&](
Value var) {
112 Type type = cast<emitc::LValueType>(var.
getType()).getValueType();
113 return emitc::LoadOp::create(rewriter, loc, type, var).getResult();
119 scf::YieldOp yield) {
130 assignValues(yieldOperands, resultVariables, rewriter, loc);
132 emitc::YieldOp::create(rewriter, loc);
148 return lowerYield(op, resultVariables, rewriter,
149 cast<scf::YieldOp>(terminator));
153 ForLowering::matchAndRewrite(ForOp forOp, OpAdaptor adaptor,
160 if (failed(createVariablesForResults(forOp, getTypeConverter(), rewriter,
163 "create variables for results failed");
165 assignValues(adaptor.getInitArgs(), resultVariables, rewriter, loc);
167 emitc::ForOp loweredFor =
168 emitc::ForOp::create(rewriter, loc, adaptor.getLowerBound(),
169 adaptor.getUpperBound(), adaptor.getStep());
171 Block *loweredBody = loweredFor.getBody();
180 loadValues(resultVariables, rewriter, loc);
187 *getTypeConverter(),
nullptr))) {
193 Block *scfBody = &(forOp.getRegion().front());
195 replacingValues.push_back(loweredFor.getInductionVar());
196 replacingValues.append(iterArgsValues.begin(), iterArgsValues.end());
197 rewriter.
mergeBlocks(scfBody, loweredBody, replacingValues);
199 auto result = lowerYield(forOp, resultVariables, rewriter,
202 if (failed(result)) {
219 matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
226 IfLowering::matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
233 if (failed(createVariablesForResults(ifOp, getTypeConverter(), rewriter,
236 "create variables for results failed");
243 auto lowerRegion = [&resultVariables, &rewriter,
245 rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.
end());
247 auto result = lowerYield(ifOp, resultVariables, rewriter,
248 cast<scf::YieldOp>(terminator));
249 if (failed(result)) {
255 Region &thenRegion = adaptor.getThenRegion();
256 Region &elseRegion = adaptor.getElseRegion();
258 bool hasElseBlock = !elseRegion.
empty();
261 emitc::IfOp::create(rewriter, loc, adaptor.getCondition(),
false,
false);
263 Region &loweredThenRegion = loweredIf.getThenRegion();
264 auto result = lowerRegion(thenRegion, loweredThenRegion);
265 if (failed(result)) {
270 Region &loweredElseRegion = loweredIf.getElseRegion();
271 auto result = lowerRegion(elseRegion, loweredElseRegion);
272 if (failed(result)) {
277 rewriter.setInsertionPointAfter(ifOp);
280 rewriter.replaceOp(ifOp, results);
290 matchAndRewrite(IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
295 IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
297 Location loc = indexSwitchOp.getLoc();
302 if (failed(createVariablesForResults(indexSwitchOp, getTypeConverter(),
303 rewriter, resultVariables))) {
305 "create variables for results failed");
309 emitc::SwitchOp::create(rewriter, loc, adaptor.getArg(),
310 adaptor.getCases(), indexSwitchOp.getNumCases());
314 llvm::zip(adaptor.getCaseRegions(), loweredSwitch.getCaseRegions())) {
315 if (failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
316 *std::get<0>(pair), std::get<1>(pair)))) {
322 if (failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
323 adaptor.getDefaultRegion(),
324 loweredSwitch.getDefaultRegion()))) {
331 rewriter.
replaceOp(indexSwitchOp, results);
342 void SCFToEmitCPass::runOnOperation() {
356 target.addIllegalOp<scf::ForOp, scf::IfOp, scf::IndexSwitchOp>();
357 target.markUnknownOpDynamicallyLegal([](
Operation *) {
return true; });
static MLIRContext * getContext(OpFoldResult val)
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
This class implements a pattern rewriter for use with ConversionPatterns.
void replaceOp(Operation *op, ValueRange newValues) override
Replace the given operation with the new values.
LogicalResult getRemappedValues(ValueRange keys, SmallVectorImpl< Value > &results)
Return the converted values that replace 'keys' with types defined by the type converter of the curre...
FailureOr< Block * > convertRegionTypes(Region *region, const TypeConverter &converter, TypeConverter::SignatureConversion *entryConversion=nullptr)
Apply a signature conversion to each block in the given region.
void eraseOp(Operation *op) override
PatternRewriter hook for erasing a dead operation.
This class describes a specific conversion target.
ConvertToEmitCPatternInterface(Dialect *dialect)
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
RAII guard to reset the insertion point of the builder when destroyed.
InsertPoint saveInsertionPoint() const
Return a saved insertion point.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
void restoreInsertionPoint(InsertPoint ip)
Restore the insert point to a previously saved point.
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
OpConversionPattern is a wrapper around ConversionPattern that allows for matching and rewriting agai...
OpConversionPattern(MLIRContext *context, PatternBenefit benefit=1)
This is a value defined by a result of an operation.
Operation is the basic unit of execution within MLIR.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
void mergeBlocks(Block *source, Block *dest, ValueRange argValues={})
Inline the operations of block 'source' into the end of block 'dest'.
void inlineRegionBefore(Region ®ion, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
void addConversion(FnT &&callback)
Register a conversion function.
LogicalResult convertType(Type t, SmallVectorImpl< Type > &results) const
Convert the given type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
bool isSupportedEmitCType(mlir::Type type)
Determines whether type is valid in EmitC.
Include the generated interface declarations.
void populateEmitCSizeTTypeConversions(TypeConverter &converter)
void populateSCFToEmitCConversionPatterns(RewritePatternSet &patterns, TypeConverter &typeConverter)
Collect a set of patterns to convert SCF operations to the EmitC dialect.
const FrozenRewritePatternSet & patterns
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, ConversionConfig config=ConversionConfig())
Below we define several entry points for operation conversion.
void registerConvertSCFToEmitCInterface(DialectRegistry ®istry)
LogicalResult matchAndRewrite(IndexSwitchOp indexSwitchOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
Methods that operate on the SourceOp type.