29 #define GEN_PASS_DEF_SCFTOEMITC
30 #include "mlir/Conversion/Passes.h.inc"
44 void populateConvertToEmitCConversionPatterns(
55 dialect->addInterfaces<SCFToEmitCDialectInterface>();
61 struct SCFToEmitCPass :
public impl::SCFToEmitCBase<SCFToEmitCPass> {
62 void runOnOperation()
override;
71 matchAndRewrite(ForOp forOp, OpAdaptor adaptor,
78 createVariablesForResults(T op,
const TypeConverter *typeConverter,
81 if (!op.getNumResults())
90 for (
OpResult result : op.getResults()) {
96 emitc::VariableOp var =
97 rewriter.
create<emitc::VariableOp>(loc, varType, noInit);
98 resultVariables.push_back(var);
108 for (
auto [value, var] : llvm::zip(values, variables))
109 rewriter.
create<emitc::AssignOp>(loc, var, value);
114 return llvm::map_to_vector<>(variables, [&](
Value var) {
115 Type type = cast<emitc::LValueType>(var.
getType()).getValueType();
116 return rewriter.
create<emitc::LoadOp>(loc, type, var).getResult();
122 scf::YieldOp yield) {
133 assignValues(yieldOperands, resultVariables, rewriter, loc);
135 rewriter.
create<emitc::YieldOp>(loc);
151 return lowerYield(op, resultVariables, rewriter,
152 cast<scf::YieldOp>(terminator));
156 ForLowering::matchAndRewrite(ForOp forOp, OpAdaptor adaptor,
163 if (failed(createVariablesForResults(forOp, getTypeConverter(), rewriter,
166 "create variables for results failed");
168 assignValues(adaptor.getInitArgs(), resultVariables, rewriter, loc);
170 emitc::ForOp loweredFor = rewriter.
create<emitc::ForOp>(
171 loc, adaptor.getLowerBound(), adaptor.getUpperBound(), adaptor.getStep());
173 Block *loweredBody = loweredFor.getBody();
176 rewriter.
eraseOp(loweredBody->getTerminator());
182 loadValues(resultVariables, rewriter, loc);
189 *getTypeConverter(),
nullptr))) {
195 Block *scfBody = &(forOp.getRegion().front());
197 replacingValues.push_back(loweredFor.getInductionVar());
198 replacingValues.append(iterArgsValues.begin(), iterArgsValues.end());
199 rewriter.
mergeBlocks(scfBody, loweredBody, replacingValues);
201 auto result = lowerYield(forOp, resultVariables, rewriter,
202 cast<scf::YieldOp>(loweredBody->getTerminator()));
204 if (failed(result)) {
221 matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
228 IfLowering::matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
235 if (failed(createVariablesForResults(ifOp, getTypeConverter(), rewriter,
238 "create variables for results failed");
245 auto lowerRegion = [&resultVariables, &rewriter,
247 rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.
end());
249 auto result = lowerYield(ifOp, resultVariables, rewriter,
250 cast<scf::YieldOp>(terminator));
251 if (failed(result)) {
257 Region &thenRegion = adaptor.getThenRegion();
258 Region &elseRegion = adaptor.getElseRegion();
260 bool hasElseBlock = !elseRegion.
empty();
263 rewriter.create<emitc::IfOp>(loc, adaptor.getCondition(),
false,
false);
265 Region &loweredThenRegion = loweredIf.getThenRegion();
266 auto result = lowerRegion(thenRegion, loweredThenRegion);
267 if (failed(result)) {
272 Region &loweredElseRegion = loweredIf.getElseRegion();
273 auto result = lowerRegion(elseRegion, loweredElseRegion);
274 if (failed(result)) {
279 rewriter.setInsertionPointAfter(ifOp);
282 rewriter.replaceOp(ifOp, results);
292 matchAndRewrite(IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
297 IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
299 Location loc = indexSwitchOp.getLoc();
304 if (failed(createVariablesForResults(indexSwitchOp, getTypeConverter(),
305 rewriter, resultVariables))) {
307 "create variables for results failed");
310 auto loweredSwitch = rewriter.
create<emitc::SwitchOp>(
311 loc, adaptor.getArg(), adaptor.getCases(), indexSwitchOp.getNumCases());
315 llvm::zip(adaptor.getCaseRegions(), loweredSwitch.getCaseRegions())) {
316 if (failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
317 *std::get<0>(pair), std::get<1>(pair)))) {
323 if (failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
324 adaptor.getDefaultRegion(),
325 loweredSwitch.getDefaultRegion()))) {
332 rewriter.
replaceOp(indexSwitchOp, results);
343 void SCFToEmitCPass::runOnOperation() {
357 target.addIllegalOp<scf::ForOp, scf::IfOp, scf::IndexSwitchOp>();
358 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.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
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=std::nullopt)
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.