MLIR 23.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
21using namespace mlir;
22using namespace emitc;
23
24namespace mlir {
25namespace emitc {
26#define GEN_PASS_DEF_WRAPFUNCINCLASSPASS
27#include "mlir/Dialect/EmitC/Transforms/Passes.h.inc"
28
29namespace {
30struct WrapFuncInClassPass
31 : public impl::WrapFuncInClassPassBase<WrapFuncInClassPass> {
32 using WrapFuncInClassPassBase::WrapFuncInClassPassBase;
33 void runOnOperation() override {
34 mlir::ModuleOp moduleOp = getOperation();
35
37
38 SymbolTableCollection symbolTable;
39 moduleOp.walk([&globalsUsedByFuncs, &symbolTable](FuncOp funcOp) {
40 funcOp.walk([&globalsUsedByFuncs, &symbolTable,
41 &funcOp](GetGlobalOp getGlobalOp) {
42 if (auto globalOp = symbolTable.lookupNearestSymbolFrom<GlobalOp>(
43 getGlobalOp, getGlobalOp.getNameAttr())) {
44 globalsUsedByFuncs[funcOp].insert(globalOp);
45 }
46 });
47 });
48
49 RewritePatternSet patterns(&getContext());
50 populateWrapFuncInClass(patterns, funcName, globalsUsedByFuncs);
51
52 walkAndApplyPatterns(moduleOp, std::move(patterns));
53
54 DenseSet<GlobalOp> globalsToErase;
55 for (auto &[_, globals] : globalsUsedByFuncs)
56 globalsToErase.insert_range(globals);
57
58 for (GlobalOp globalOp : globalsToErase)
59 globalOp.erase();
60 }
61};
62
63} // namespace
64} // namespace emitc
65} // namespace mlir
66
67class WrapFuncInClass : public OpRewritePattern<FuncOp> {
68public:
70 MLIRContext *context, StringRef funcName,
71 const DenseMap<FuncOp, llvm::DenseSet<GlobalOp>> &globalsToMove)
72 : OpRewritePattern<FuncOp>(context), funcName(funcName),
73 globalsToMove(globalsToMove) {}
74
75 LogicalResult matchAndRewrite(FuncOp funcOp,
76 PatternRewriter &rewriter) const override {
77
78 auto className = funcOp.getSymNameAttr().str() + "Class";
79 ClassOp newClassOp = ClassOp::create(rewriter, funcOp.getLoc(), className);
80
82 rewriter.createBlock(&newClassOp.getBody());
83 rewriter.setInsertionPointToStart(&newClassOp.getBody().front());
84
85 auto argAttrs = funcOp.getArgAttrs();
86 for (auto [idx, val] : llvm::enumerate(funcOp.getArguments())) {
87 StringAttr fieldName =
88 rewriter.getStringAttr("fieldName" + std::to_string(idx));
89
90 TypeAttr typeAttr = TypeAttr::get(val.getType());
91 fields.push_back({fieldName, typeAttr});
92
93 FieldOp fieldop = FieldOp::create(rewriter, funcOp->getLoc(), fieldName,
94 typeAttr, nullptr);
95
96 if (argAttrs && idx < argAttrs->size()) {
97 fieldop->setDiscardableAttrs(funcOp.getArgAttrDict(idx));
98 }
99 }
100
101 auto globalsIt = globalsToMove.find(funcOp);
102 if (globalsIt != globalsToMove.end()) {
103 for (auto global : globalsIt->second) {
104 FieldOp::create(rewriter, funcOp->getLoc(), global.getSymNameAttr(),
105 global.getTypeAttr(), global.getInitialValueAttr());
106 }
107 }
108
109 rewriter.setInsertionPointToEnd(&newClassOp.getBody().front());
110 FunctionType funcType = funcOp.getFunctionType();
111 Location loc = funcOp.getLoc();
112 FuncOp newFuncOp = FuncOp::create(rewriter, loc, (funcName), funcType);
114 rewriter.createBlock(&newFuncOp.getBody());
115 newFuncOp.getBody().takeBody(funcOp.getBody());
117 rewriter.setInsertionPointToStart(&newFuncOp.getBody().front());
118 std::vector<Value> newArguments;
119 newArguments.reserve(fields.size());
120 for (auto &[fieldName, attr] : fields) {
121 GetFieldOp arg =
122 GetFieldOp::create(rewriter, loc, attr.getValue(), fieldName);
123 newArguments.push_back(arg);
125
126 for (auto [oldArg, newArg] :
127 llvm::zip(newFuncOp.getArguments(), newArguments)) {
128 rewriter.replaceAllUsesWith(oldArg, newArg);
130
131 llvm::BitVector argsToErase(newFuncOp.getNumArguments(), true);
132 if (failed(newFuncOp.eraseArguments(argsToErase)))
133 newFuncOp->emitOpError("failed to erase all arguments using BitVector");
134
135 newFuncOp.walk([&](GetGlobalOp getGlobalOp) {
136 rewriter.setInsertionPoint(getGlobalOp);
137 GetFieldOp getFieldOp =
138 GetFieldOp::create(rewriter, getGlobalOp.getLoc(),
139 getGlobalOp.getType(), getGlobalOp.getNameAttr());
140 rewriter.replaceOp(getGlobalOp, getFieldOp);
141 });
142
143 rewriter.replaceOp(funcOp, newClassOp);
144 return success();
146
147private:
148 /// Name of the newly generated member function with body matching the input
149 /// function.
150 std::string funcName;
151
152 /// Map of FuncOp and the GlobalOps it uses which need to be moved into the
153 /// ClassOp wrapper.
158 RewritePatternSet &patterns, StringRef funcName,
159 DenseMap<FuncOp, DenseSet<GlobalOp>> &globalsToMove) {
160 patterns.add<WrapFuncInClass>(patterns.getContext(), funcName, globalsToMove);
return success()
b getContext())
WrapFuncInClass(MLIRContext *context, StringRef funcName, const DenseMap< FuncOp, llvm::DenseSet< GlobalOp > > &globalsToMove)
LogicalResult matchAndRewrite(FuncOp funcOp, PatternRewriter &rewriter) const override
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
Definition Builders.h:93
StringAttr getStringAttr(const Twine &bytes)
Definition Builders.cpp:267
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:435
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition Builders.h:433
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:400
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:438
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,...
::mlir::Pass::Option< std::string > funcName
void populateWrapFuncInClass(RewritePatternSet &patterns, StringRef funcName, 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={})