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 rewriter.
create<emitc::VariableOp>(loc, varType, noInit);
95 resultVariables.push_back(var);
105 for (
auto [value, var] : llvm::zip(values, variables))
106 rewriter.
create<emitc::AssignOp>(loc, var, value);
111 return llvm::map_to_vector<>(variables, [&](
Value var) {
112 Type type = cast<emitc::LValueType>(var.
getType()).getValueType();
113 return rewriter.
create<emitc::LoadOp>(loc, type, var).getResult();
119 scf::YieldOp yield) {
130 assignValues(yieldOperands, resultVariables, rewriter, loc);
132 rewriter.
create<emitc::YieldOp>(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 = rewriter.
create<emitc::ForOp>(
168 loc, adaptor.getLowerBound(), adaptor.getUpperBound(), adaptor.getStep());
170 Block *loweredBody = loweredFor.getBody();
173 rewriter.
eraseOp(loweredBody->getTerminator());
179 loadValues(resultVariables, rewriter, loc);
186 *getTypeConverter(),
nullptr))) {
192 Block *scfBody = &(forOp.getRegion().front());
194 replacingValues.push_back(loweredFor.getInductionVar());
195 replacingValues.append(iterArgsValues.begin(), iterArgsValues.end());
196 rewriter.
mergeBlocks(scfBody, loweredBody, replacingValues);
198 auto result = lowerYield(forOp, resultVariables, rewriter,
199 cast<scf::YieldOp>(loweredBody->getTerminator()));
201 if (failed(result)) {
218 matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
225 IfLowering::matchAndRewrite(IfOp ifOp, OpAdaptor adaptor,
232 if (failed(createVariablesForResults(ifOp, getTypeConverter(), rewriter,
235 "create variables for results failed");
242 auto lowerRegion = [&resultVariables, &rewriter,
244 rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.
end());
246 auto result = lowerYield(ifOp, resultVariables, rewriter,
247 cast<scf::YieldOp>(terminator));
248 if (failed(result)) {
254 Region &thenRegion = adaptor.getThenRegion();
255 Region &elseRegion = adaptor.getElseRegion();
257 bool hasElseBlock = !elseRegion.
empty();
260 rewriter.create<emitc::IfOp>(loc, adaptor.getCondition(),
false,
false);
262 Region &loweredThenRegion = loweredIf.getThenRegion();
263 auto result = lowerRegion(thenRegion, loweredThenRegion);
264 if (failed(result)) {
269 Region &loweredElseRegion = loweredIf.getElseRegion();
270 auto result = lowerRegion(elseRegion, loweredElseRegion);
271 if (failed(result)) {
276 rewriter.setInsertionPointAfter(ifOp);
279 rewriter.replaceOp(ifOp, results);
289 matchAndRewrite(IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
294 IndexSwitchOp indexSwitchOp,
OpAdaptor adaptor,
296 Location loc = indexSwitchOp.getLoc();
301 if (failed(createVariablesForResults(indexSwitchOp, getTypeConverter(),
302 rewriter, resultVariables))) {
304 "create variables for results failed");
307 auto loweredSwitch = rewriter.
create<emitc::SwitchOp>(
308 loc, adaptor.getArg(), adaptor.getCases(), indexSwitchOp.getNumCases());
312 llvm::zip(adaptor.getCaseRegions(), loweredSwitch.getCaseRegions())) {
313 if (failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
314 *std::get<0>(pair), std::get<1>(pair)))) {
320 if (failed(lowerRegion(indexSwitchOp, resultVariables, rewriter,
321 adaptor.getDefaultRegion(),
322 loweredSwitch.getDefaultRegion()))) {
329 rewriter.
replaceOp(indexSwitchOp, results);
340 void SCFToEmitCPass::runOnOperation() {
354 target.addIllegalOp<scf::ForOp, scf::IfOp, scf::IndexSwitchOp>();
355 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={})
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.