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,
157 if (forOp.getUnsignedCmp())
159 "unsigned loops are not supported");
164 if (
failed(createVariablesForResults(forOp, getTypeConverter(), rewriter,
167 "create variables for results failed");
169 assignValues(adaptor.getInitArgs(), resultVariables, rewriter, loc);
171 emitc::ForOp loweredFor =
172 emitc::ForOp::create(rewriter, loc, adaptor.getLowerBound(),
173 adaptor.getUpperBound(), adaptor.getStep());
175 Block *loweredBody = loweredFor.getBody();
184 loadValues(resultVariables, rewriter, loc);
191 *getTypeConverter(),
nullptr))) {
197 Block *scfBody = &(forOp.getRegion().front());
199 replacingValues.push_back(loweredFor.getInductionVar());
200 replacingValues.append(iterArgsValues.begin(), iterArgsValues.end());
201 rewriter.
mergeBlocks(scfBody, loweredBody, replacingValues);
203 auto result = lowerYield(forOp, resultVariables, rewriter,
223 matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
230 IfLowering::matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
237 if (
failed(createVariablesForResults(ifOp, getTypeConverter(), rewriter,
240 "create variables for results failed");
247 auto lowerRegion = [&resultVariables, &rewriter,
249 rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.
end());
251 auto result = lowerYield(ifOp, resultVariables, rewriter,
252 cast<scf::YieldOp>(terminator));
259 Region &thenRegion = adaptor.getThenRegion();
260 Region &elseRegion = adaptor.getElseRegion();
262 bool hasElseBlock = !elseRegion.
empty();
265 emitc::IfOp::create(rewriter, loc, adaptor.getCondition(),
false,
false);
267 Region &loweredThenRegion = loweredIf.getThenRegion();
268 auto result = lowerRegion(thenRegion, loweredThenRegion);
274 Region &loweredElseRegion = loweredIf.getElseRegion();
275 auto result = lowerRegion(elseRegion, loweredElseRegion);
281 rewriter.setInsertionPointAfter(ifOp);
284 rewriter.replaceOp(ifOp, results);
294 matchAndRewrite(IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
299 IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
301 Location loc = indexSwitchOp.getLoc();
306 if (
failed(createVariablesForResults(indexSwitchOp, getTypeConverter(),
307 rewriter, resultVariables))) {
309 "create variables for results failed");
313 emitc::SwitchOp::create(rewriter, loc, adaptor.getArg(),
314 adaptor.getCases(), indexSwitchOp.getNumCases());
318 llvm::zip(adaptor.getCaseRegions(), loweredSwitch.getCaseRegions())) {
319 if (
failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
320 *std::get<0>(pair), std::get<1>(pair)))) {
326 if (
failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
327 adaptor.getDefaultRegion(),
328 loweredSwitch.getDefaultRegion()))) {
335 rewriter.
replaceOp(indexSwitchOp, results);
346 void SCFToEmitCPass::runOnOperation() {
360 target.addIllegalOp<scf::ForOp, scf::IfOp, scf::IndexSwitchOp>();
361 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.