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 /*sym_visibility=*/nullptr);
84
86 rewriter.createBlock(&newClassOp.getBody());
87 rewriter.setInsertionPointToStart(&newClassOp.getBody().front());
88
89 auto argAttrs = funcOp.getArgAttrs();
90 for (auto [idx, val] : llvm::enumerate(funcOp.getArguments())) {
91 StringAttr fieldName =
92 rewriter.getStringAttr("fieldName" + std::to_string(idx));
93
94 TypeAttr typeAttr = TypeAttr::get(val.getType());
95 fields.push_back({fieldName, typeAttr});
96
97 FieldOp fieldop =
98 FieldOp::create(rewriter, funcOp->getLoc(), fieldName,
99 /*sym_visibility=*/nullptr, typeAttr, nullptr);
100
101 if (argAttrs && idx < argAttrs->size()) {
102 fieldop->setDiscardableAttrs(funcOp.getArgAttrDict(idx));
103 }
104 }
105
106 auto globalsIt = globalsToMove.find(funcOp);
107 if (globalsIt != globalsToMove.end()) {
108 for (auto global : globalsIt->second) {
109 FieldOp::create(rewriter, funcOp->getLoc(), global.getSymNameAttr(),
110 /*sym_visibility=*/nullptr, global.getTypeAttr(),
111 global.getInitialValueAttr());
112 }
113 }
114
115 rewriter.setInsertionPointToEnd(&newClassOp.getBody().front());
116 FunctionType funcType = funcOp.getFunctionType();
117 Location loc = funcOp.getLoc();
118 FuncOp newFuncOp = FuncOp::create(rewriter, loc, (funcName), funcType);
119
120 // Rewrite globals while they are still descendants of the matched op.
121 funcOp.walk([&](GetGlobalOp getGlobalOp) {
122 rewriter.setInsertionPoint(getGlobalOp);
123 GetFieldOp getFieldOp =
124 GetFieldOp::create(rewriter, getGlobalOp.getLoc(),
125 getGlobalOp.getType(), getGlobalOp.getNameAttr());
126 rewriter.replaceOp(getGlobalOp, getFieldOp);
127 });
128
129 rewriter.createBlock(&newFuncOp.getBody());
130 newFuncOp.getBody().takeBody(funcOp.getBody());
131
132 rewriter.setInsertionPointToStart(&newFuncOp.getBody().front());
133 std::vector<Value> newArguments;
134 newArguments.reserve(fields.size());
135 for (auto &[fieldName, attr] : fields) {
136 GetFieldOp arg =
137 GetFieldOp::create(rewriter, loc, attr.getValue(), fieldName);
138 newArguments.push_back(arg);
139 }
140
141 for (auto [oldArg, newArg] :
142 llvm::zip(newFuncOp.getArguments(), newArguments)) {
143 rewriter.replaceAllUsesWith(oldArg, newArg);
144 }
145
146 llvm::BitVector argsToErase(newFuncOp.getNumArguments(), true);
147 if (failed(newFuncOp.eraseArguments(argsToErase)))
148 newFuncOp->emitOpError("failed to erase all arguments using BitVector");
149
150 rewriter.replaceOp(funcOp, newClassOp);
151 return success();
152 }
153
154private:
155 /// Name of the newly generated member function with body matching the input
156 /// function.
157 std::string funcName;
158
159 /// Format string used to create the wrapper class name where the
160 /// function-name placeholder '{}' is optional.
161 std::string classNameFormat;
162
163 /// Map of FuncOp and the GlobalOps it uses which need to be moved into the
164 /// ClassOp wrapper.
166};
167
169 RewritePatternSet &patterns, StringRef funcName, StringRef classNameFormat,
170 DenseMap<FuncOp, DenseSet<GlobalOp>> &globalsToMove) {
171 patterns.add<WrapFuncInClass>(patterns.getContext(), funcName,
172 classNameFormat, globalsToMove);
173}
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={})