MLIR 24.0.0git
WrapFuncInClass.cpp
Go to the documentation of this file.
1//===- WrapFuncInClass.cpp - Wrap Emitc Funcs in classes -------------===//
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
12#include "mlir/IR/Attributes.h"
13#include "mlir/IR/Builders.h"
16#include "mlir/IR/SymbolTable.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/DenseSet.h"
20#include "llvm/Support/FormatVariadic.h"
21
22using namespace mlir;
23using namespace emitc;
24
25namespace mlir {
26namespace emitc {
27#define GEN_PASS_DEF_WRAPFUNCINCLASSPASS
28#include "mlir/Dialect/EmitC/Transforms/Passes.h.inc"
29
30namespace {
31struct WrapFuncInClassPass
32 : public impl::WrapFuncInClassPassBase<WrapFuncInClassPass> {
33 using WrapFuncInClassPassBase::WrapFuncInClassPassBase;
34 void runOnOperation() override {
35 mlir::ModuleOp moduleOp = getOperation();
36
38
39 SymbolTableCollection symbolTable;
40 moduleOp.walk([&globalsUsedByFuncs, &symbolTable](FuncOp funcOp) {
41 funcOp.walk([&globalsUsedByFuncs, &symbolTable,
42 &funcOp](GetGlobalOp getGlobalOp) {
43 if (auto globalOp = symbolTable.lookupNearestSymbolFrom<GlobalOp>(
44 getGlobalOp, getGlobalOp.getNameAttr())) {
45 globalsUsedByFuncs[funcOp].insert(globalOp);
46 }
47 });
48 });
49
50 RewritePatternSet patterns(&getContext());
51 populateWrapFuncInClass(patterns, funcName, classNameFormat,
52 globalsUsedByFuncs);
53
54 walkAndApplyPatterns(moduleOp, std::move(patterns));
55
56 DenseSet<GlobalOp> globalsToErase;
57 for (auto &[_, globals] : globalsUsedByFuncs)
58 globalsToErase.insert_range(globals);
59
60 for (GlobalOp globalOp : globalsToErase)
61 globalOp.erase();
62 }
63};
64
65} // namespace
66} // namespace emitc
67} // namespace mlir
68
69class WrapFuncInClass : public OpRewritePattern<FuncOp> {
70public:
72 MLIRContext *context, StringRef funcName, StringRef classNameFormat,
73 const DenseMap<FuncOp, llvm::DenseSet<GlobalOp>> &globalsToMove)
74 : OpRewritePattern<FuncOp>(context), funcName(funcName),
75 classNameFormat(classNameFormat), globalsToMove(globalsToMove) {}
76
77 LogicalResult matchAndRewrite(FuncOp funcOp,
78 PatternRewriter &rewriter) const override {
79
80 std::string className =
81 llvm::formatv(classNameFormat.c_str(), funcOp.getName());
82 ClassOp newClassOp = ClassOp::create(rewriter, funcOp.getLoc(), className);
83
85 rewriter.createBlock(&newClassOp.getBody());
86 rewriter.setInsertionPointToStart(&newClassOp.getBody().front());
87
88 auto argAttrs = funcOp.getArgAttrs();
89 for (auto [idx, val] : llvm::enumerate(funcOp.getArguments())) {
90 StringAttr fieldName =
91 rewriter.getStringAttr("fieldName" + std::to_string(idx));
92
93 TypeAttr typeAttr = TypeAttr::get(val.getType());
94 fields.push_back({fieldName, typeAttr});
95
96 FieldOp fieldop = FieldOp::create(rewriter, funcOp->getLoc(), fieldName,
97 typeAttr, nullptr);
98
99 if (argAttrs && idx < argAttrs->size()) {
100 fieldop->setDiscardableAttrs(funcOp.getArgAttrDict(idx));
101 }
102 }
103
104 auto globalsIt = globalsToMove.find(funcOp);
105 if (globalsIt != globalsToMove.end()) {
106 for (auto global : globalsIt->second) {
107 FieldOp::create(rewriter, funcOp->getLoc(), global.getSymNameAttr(),
108 global.getTypeAttr(), global.getInitialValueAttr());
109 }
110 }
111
112 rewriter.setInsertionPointToEnd(&newClassOp.getBody().front());
113 FunctionType funcType = funcOp.getFunctionType();
114 Location loc = funcOp.getLoc();
115 FuncOp newFuncOp = FuncOp::create(rewriter, loc, (funcName), funcType);
116
117 rewriter.createBlock(&newFuncOp.getBody());
118 newFuncOp.getBody().takeBody(funcOp.getBody());
119
120 rewriter.setInsertionPointToStart(&newFuncOp.getBody().front());
121 std::vector<Value> newArguments;
122 newArguments.reserve(fields.size());
123 for (auto &[fieldName, attr] : fields) {
124 GetFieldOp arg =
125 GetFieldOp::create(rewriter, loc, attr.getValue(), fieldName);
126 newArguments.push_back(arg);
127 }
128
129 for (auto [oldArg, newArg] :
130 llvm::zip(newFuncOp.getArguments(), newArguments)) {
131 rewriter.replaceAllUsesWith(oldArg, newArg);
132 }
133
134 llvm::BitVector argsToErase(newFuncOp.getNumArguments(), true);
135 if (failed(newFuncOp.eraseArguments(argsToErase)))
136 newFuncOp->emitOpError("failed to erase all arguments using BitVector");
137
138 newFuncOp.walk([&](GetGlobalOp getGlobalOp) {
139 rewriter.setInsertionPoint(getGlobalOp);
140 GetFieldOp getFieldOp =
141 GetFieldOp::create(rewriter, getGlobalOp.getLoc(),
142 getGlobalOp.getType(), getGlobalOp.getNameAttr());
143 rewriter.replaceOp(getGlobalOp, getFieldOp);
144 });
145
146 rewriter.replaceOp(funcOp, newClassOp);
147 return success();
148 }
149
150private:
151 /// Name of the newly generated member function with body matching the input
152 /// function.
153 std::string funcName;
154
155 /// Format string used to create the wrapper class name where '{}' is
156 /// replaced with the original function name.
157 std::string classNameFormat;
158
159 /// Map of FuncOp and the GlobalOps it uses which need to be moved into the
160 /// ClassOp wrapper.
162};
163
165 RewritePatternSet &patterns, StringRef funcName, StringRef classNameFormat,
166 DenseMap<FuncOp, DenseSet<GlobalOp>> &globalsToMove) {
167 patterns.add<WrapFuncInClass>(patterns.getContext(), funcName,
168 classNameFormat, globalsToMove);
169}
return success()
b getContext())
LogicalResult matchAndRewrite(FuncOp funcOp, PatternRewriter &rewriter) const override
WrapFuncInClass(MLIRContext *context, StringRef funcName, StringRef classNameFormat, const DenseMap< FuncOp, llvm::DenseSet< GlobalOp > > &globalsToMove)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
Definition Builders.h:94
StringAttr getStringAttr(const Twine &bytes)
Definition Builders.cpp:271
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Definition Builders.cpp:439
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition Builders.h:434
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:401
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:439
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
virtual void replaceAllUsesWith(Value from, Value to)
Find uses of from and replace them with to.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
void populateWrapFuncInClass(RewritePatternSet &patterns, StringRef funcName, StringRef classNameFormat, DenseMap< FuncOp, llvm::DenseSet< GlobalOp > > &globalsToMove)
Include the generated interface declarations.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Definition LLVM.h:122
void walkAndApplyPatterns(Operation *op, const FrozenRewritePatternSet &patterns, RewriterBase::Listener *listener=nullptr)
A fast walk-based pattern rewrite driver.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:120
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})