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 = llvm::formatv(
81 /*Validate=*/false, 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 // Rewrite globals while they are still descendants of the matched op.
118 funcOp.walk([&](GetGlobalOp getGlobalOp) {
119 rewriter.setInsertionPoint(getGlobalOp);
120 GetFieldOp getFieldOp =
121 GetFieldOp::create(rewriter, getGlobalOp.getLoc(),
122 getGlobalOp.getType(), getGlobalOp.getNameAttr());
123 rewriter.replaceOp(getGlobalOp, getFieldOp);
124 });
125
126 rewriter.createBlock(&newFuncOp.getBody());
127 newFuncOp.getBody().takeBody(funcOp.getBody());
128
129 rewriter.setInsertionPointToStart(&newFuncOp.getBody().front());
130 std::vector<Value> newArguments;
131 newArguments.reserve(fields.size());
132 for (auto &[fieldName, attr] : fields) {
133 GetFieldOp arg =
134 GetFieldOp::create(rewriter, loc, attr.getValue(), fieldName);
135 newArguments.push_back(arg);
136 }
137
138 for (auto [oldArg, newArg] :
139 llvm::zip(newFuncOp.getArguments(), newArguments)) {
140 rewriter.replaceAllUsesWith(oldArg, newArg);
141 }
142
143 llvm::BitVector argsToErase(newFuncOp.getNumArguments(), true);
144 if (failed(newFuncOp.eraseArguments(argsToErase)))
145 newFuncOp->emitOpError("failed to erase all arguments using BitVector");
146
147 rewriter.replaceOp(funcOp, newClassOp);
148 return success();
149 }
150
151private:
152 /// Name of the newly generated member function with body matching the input
153 /// function.
154 std::string funcName;
155
156 /// Format string used to create the wrapper class name where the
157 /// function-name placeholder '{}' is optional.
158 std::string classNameFormat;
159
160 /// Map of FuncOp and the GlobalOps it uses which need to be moved into the
161 /// ClassOp wrapper.
163};
164
166 RewritePatternSet &patterns, StringRef funcName, StringRef classNameFormat,
167 DenseMap<FuncOp, DenseSet<GlobalOp>> &globalsToMove) {
168 patterns.add<WrapFuncInClass>(patterns.getContext(), funcName,
169 classNameFormat, globalsToMove);
170}
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={})