MLIR  20.0.0git
FuncToEmitC.cpp
Go to the documentation of this file.
1 //===- FuncToEmitC.cpp - Func to EmitC Patterns -----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements patterns to convert the Func dialect to the EmitC
10 // dialect.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 
19 
20 using namespace mlir;
21 
22 //===----------------------------------------------------------------------===//
23 // Conversion Patterns
24 //===----------------------------------------------------------------------===//
25 
26 namespace {
27 class CallOpConversion final : public OpConversionPattern<func::CallOp> {
28 public:
30 
31  LogicalResult
32  matchAndRewrite(func::CallOp callOp, OpAdaptor adaptor,
33  ConversionPatternRewriter &rewriter) const override {
34  // Multiple results func cannot be converted to `emitc.func`.
35  if (callOp.getNumResults() > 1)
36  return rewriter.notifyMatchFailure(
37  callOp, "only functions with zero or one result can be converted");
38 
39  rewriter.replaceOpWithNewOp<emitc::CallOp>(callOp, callOp.getResultTypes(),
40  adaptor.getOperands(),
41  callOp->getAttrs());
42 
43  return success();
44  }
45 };
46 
47 class FuncOpConversion final : public OpConversionPattern<func::FuncOp> {
48 public:
50 
51  LogicalResult
52  matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
53  ConversionPatternRewriter &rewriter) const override {
54 
55  if (funcOp.getFunctionType().getNumResults() > 1)
56  return rewriter.notifyMatchFailure(
57  funcOp, "only functions with zero or one result can be converted");
58 
59  // Create the converted `emitc.func` op.
60  emitc::FuncOp newFuncOp = rewriter.create<emitc::FuncOp>(
61  funcOp.getLoc(), funcOp.getName(), funcOp.getFunctionType());
62 
63  // Copy over all attributes other than the function name and type.
64  for (const auto &namedAttr : funcOp->getAttrs()) {
65  if (namedAttr.getName() != funcOp.getFunctionTypeAttrName() &&
66  namedAttr.getName() != SymbolTable::getSymbolAttrName())
67  newFuncOp->setAttr(namedAttr.getName(), namedAttr.getValue());
68  }
69 
70  // Add `extern` to specifiers if `func.func` is declaration only.
71  if (funcOp.isDeclaration()) {
72  ArrayAttr specifiers = rewriter.getStrArrayAttr({"extern"});
73  newFuncOp.setSpecifiersAttr(specifiers);
74  }
75 
76  // Add `static` to specifiers if `func.func` is private but not a
77  // declaration.
78  if (funcOp.isPrivate() && !funcOp.isDeclaration()) {
79  ArrayAttr specifiers = rewriter.getStrArrayAttr({"static"});
80  newFuncOp.setSpecifiersAttr(specifiers);
81  }
82 
83  if (!funcOp.isDeclaration())
84  rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
85  newFuncOp.end());
86  rewriter.eraseOp(funcOp);
87 
88  return success();
89  }
90 };
91 
92 class ReturnOpConversion final : public OpConversionPattern<func::ReturnOp> {
93 public:
95 
96  LogicalResult
97  matchAndRewrite(func::ReturnOp returnOp, OpAdaptor adaptor,
98  ConversionPatternRewriter &rewriter) const override {
99  if (returnOp.getNumOperands() > 1)
100  return rewriter.notifyMatchFailure(
101  returnOp, "only zero or one operand is supported");
102 
103  rewriter.replaceOpWithNewOp<emitc::ReturnOp>(
104  returnOp,
105  returnOp.getNumOperands() ? adaptor.getOperands()[0] : nullptr);
106  return success();
107  }
108 };
109 } // namespace
110 
111 //===----------------------------------------------------------------------===//
112 // Pattern population
113 //===----------------------------------------------------------------------===//
114 
116  MLIRContext *ctx = patterns.getContext();
117 
118  patterns.add<CallOpConversion, FuncOpConversion, ReturnOpConversion>(ctx);
119 }
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Definition: Builders.cpp:346
This class implements a pattern rewriter for use with ConversionPatterns.
void eraseOp(Operation *op) override
PatternRewriter hook for erasing a dead operation.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:497
OpConversionPattern is a wrapper around ConversionPattern that allows for matching and rewriting agai...
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
Definition: Operation.h:582
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,...
Definition: PatternMatch.h:724
void inlineRegionBefore(Region &region, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
Definition: PatternMatch.h:542
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Definition: SymbolTable.h:76
Include the generated interface declarations.
void populateFuncToEmitCPatterns(RewritePatternSet &patterns)
const FrozenRewritePatternSet & patterns