blob: 80b30c6c3a77912312babf48f46764c591a9bf1c [file] [log] [blame]
Chris Lattner158e0a3e2018-07-08 20:51:38 -07001//===- Builders.h - Helpers for constructing MLIR Classes -------*- C++ -*-===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17
18#ifndef MLIR_IR_BUILDERS_H
19#define MLIR_IR_BUILDERS_H
20
Uday Bondhugula15984952018-08-01 22:36:12 -070021#include "mlir/IR/Attributes.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070022#include "mlir/IR/CFGFunction.h"
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070023#include "mlir/IR/MLFunction.h"
24#include "mlir/IR/Statements.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070025
26namespace mlir {
27class MLIRContext;
28class Module;
29class Type;
30class PrimitiveType;
31class IntegerType;
32class FunctionType;
33class VectorType;
34class RankedTensorType;
35class UnrankedTensorType;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070036class BoolAttr;
37class IntegerAttr;
38class FloatAttr;
39class StringAttr;
James Molloyf0d2f442018-08-03 01:54:46 -070040class TypeAttr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070041class ArrayAttr;
MLIR Teamb61885d2018-07-18 16:29:21 -070042class AffineMapAttr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070043class AffineMap;
44class AffineExpr;
45class AffineConstantExpr;
46class AffineDimExpr;
47class AffineSymbolExpr;
Chris Lattner158e0a3e2018-07-08 20:51:38 -070048
49/// This class is a general helper class for creating context-global objects
50/// like types, attributes, and affine expressions.
51class Builder {
52public:
53 explicit Builder(MLIRContext *context) : context(context) {}
54 explicit Builder(Module *module);
55
56 MLIRContext *getContext() const { return context; }
57
Chris Lattner1ac20cb2018-07-10 10:59:53 -070058 Identifier getIdentifier(StringRef str);
59 Module *createModule();
60
Chris Lattner158e0a3e2018-07-08 20:51:38 -070061 // Types.
Chris Lattnerc3251192018-07-27 13:09:58 -070062 FloatType *getBF16Type();
63 FloatType *getF16Type();
64 FloatType *getF32Type();
65 FloatType *getF64Type();
66
67 OtherType *getAffineIntType();
68 OtherType *getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -070069 OtherType *getTFStringType();
Chris Lattner158e0a3e2018-07-08 20:51:38 -070070 IntegerType *getIntegerType(unsigned width);
71 FunctionType *getFunctionType(ArrayRef<Type *> inputs,
72 ArrayRef<Type *> results);
73 VectorType *getVectorType(ArrayRef<unsigned> shape, Type *elementType);
74 RankedTensorType *getTensorType(ArrayRef<int> shape, Type *elementType);
75 UnrankedTensorType *getTensorType(Type *elementType);
76
Chris Lattner1ac20cb2018-07-10 10:59:53 -070077 // Attributes.
78 BoolAttr *getBoolAttr(bool value);
79 IntegerAttr *getIntegerAttr(int64_t value);
80 FloatAttr *getFloatAttr(double value);
81 StringAttr *getStringAttr(StringRef bytes);
82 ArrayAttr *getArrayAttr(ArrayRef<Attribute *> value);
MLIR Teamb61885d2018-07-18 16:29:21 -070083 AffineMapAttr *getAffineMapAttr(AffineMap *value);
James Molloyf0d2f442018-08-03 01:54:46 -070084 TypeAttr *getTypeAttr(Type *type);
Chris Lattner1ac20cb2018-07-10 10:59:53 -070085
86 // Affine Expressions and Affine Map.
87 AffineMap *getAffineMap(unsigned dimCount, unsigned symbolCount,
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070088 ArrayRef<AffineExpr *> results,
89 ArrayRef<AffineExpr *> rangeSizes);
Chris Lattner1ac20cb2018-07-10 10:59:53 -070090 AffineDimExpr *getDimExpr(unsigned position);
91 AffineSymbolExpr *getSymbolExpr(unsigned position);
92 AffineConstantExpr *getConstantExpr(int64_t constant);
93 AffineExpr *getAddExpr(AffineExpr *lhs, AffineExpr *rhs);
94 AffineExpr *getSubExpr(AffineExpr *lhs, AffineExpr *rhs);
95 AffineExpr *getMulExpr(AffineExpr *lhs, AffineExpr *rhs);
96 AffineExpr *getModExpr(AffineExpr *lhs, AffineExpr *rhs);
97 AffineExpr *getFloorDivExpr(AffineExpr *lhs, AffineExpr *rhs);
98 AffineExpr *getCeilDivExpr(AffineExpr *lhs, AffineExpr *rhs);
99
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700100 // TODO: Helpers for affine map/exprs, etc.
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700101protected:
102 MLIRContext *context;
103};
104
105/// This class helps build a CFGFunction. Instructions that are created are
106/// automatically inserted at an insertion point or added to the current basic
107/// block.
108class CFGFuncBuilder : public Builder {
109public:
Chris Lattner8174f3a2018-07-29 16:45:23 -0700110 CFGFuncBuilder(BasicBlock *block, BasicBlock::iterator insertPoint)
111 : Builder(block->getFunction()->getContext()),
112 function(block->getFunction()) {
113 setInsertionPoint(block, insertPoint);
114 }
115
116 CFGFuncBuilder(OperationInst *insertBefore)
117 : CFGFuncBuilder(insertBefore->getBlock(),
118 BasicBlock::iterator(insertBefore)) {}
119
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700120 CFGFuncBuilder(BasicBlock *block)
121 : Builder(block->getFunction()->getContext()),
122 function(block->getFunction()) {
123 setInsertionPoint(block);
124 }
Chris Lattner8174f3a2018-07-29 16:45:23 -0700125
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700126 CFGFuncBuilder(CFGFunction *function)
127 : Builder(function->getContext()), function(function) {}
128
129 /// Reset the insertion point to no location. Creating an operation without a
130 /// set insertion point is an error, but this can still be useful when the
131 /// current insertion point a builder refers to is being removed.
132 void clearInsertionPoint() {
133 this->block = nullptr;
134 insertPoint = BasicBlock::iterator();
135 }
136
Chris Lattner8174f3a2018-07-29 16:45:23 -0700137 /// Set the insertion point to the specified location.
138 void setInsertionPoint(BasicBlock *block, BasicBlock::iterator insertPoint) {
139 assert(block->getFunction() == function &&
140 "can't move to a different function");
141 this->block = block;
142 this->insertPoint = insertPoint;
143 }
144
145 /// Set the insertion point to the specified operation.
146 void setInsertionPoint(OperationInst *inst) {
147 setInsertionPoint(inst->getBlock(), BasicBlock::iterator(inst));
148 }
149
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700150 /// Set the insertion point to the end of the specified block.
151 void setInsertionPoint(BasicBlock *block) {
Chris Lattner8174f3a2018-07-29 16:45:23 -0700152 setInsertionPoint(block, block->end());
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700153 }
154
Tatiana Shpeisman6708b452018-07-24 10:15:13 -0700155 // Add new basic block and set the insertion point to the end of it.
156 BasicBlock *createBlock();
157
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700158 // TODO(clattner): remove this.
159 /// Create an operation at the current insertion point.
Chris Lattner3b2ef762018-07-18 15:31:25 -0700160 OperationInst *createOperation(Identifier name, ArrayRef<CFGValue *> operands,
161 ArrayRef<Type *> resultTypes,
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700162 ArrayRef<NamedAttribute> attributes) {
Chris Lattner3b2ef762018-07-18 15:31:25 -0700163 auto op =
164 OperationInst::create(name, operands, resultTypes, attributes, context);
Chris Lattner8174f3a2018-07-29 16:45:23 -0700165 block->getOperations().insert(insertPoint, op);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700166 return op;
167 }
168
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700169 /// Create an operation given the fields represented as an OperationState.
170 OperationInst *createOperation(const OperationState &state);
171
172 // TODO(clattner): rework build to return an OperationState so the
173 // implementations can moved out of line.
174 /// Create operation of specific op type at the current insertion point.
175 template <typename OpTy, typename... Args>
176 OpPointer<OpTy> create(Args... args) {
177 return OpTy::build(this, args...);
178 }
179
Uday Bondhugula15984952018-08-01 22:36:12 -0700180 OperationInst *cloneOperation(const OperationInst &srcOpInst) {
181 auto *op = srcOpInst.clone();
182 block->getOperations().insert(insertPoint, op);
183 return op;
184 }
185
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700186 // Terminators.
187
Chris Lattner40746442018-07-21 14:32:09 -0700188 ReturnInst *createReturnInst(ArrayRef<CFGValue *> operands) {
189 return insertTerminator(ReturnInst::create(operands));
190 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700191
192 BranchInst *createBranchInst(BasicBlock *dest) {
Chris Lattner40746442018-07-21 14:32:09 -0700193 return insertTerminator(BranchInst::create(dest));
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700194 }
195
James Molloy4f788372018-07-24 15:01:27 -0700196 CondBranchInst *createCondBranchInst(CFGValue *condition,
197 BasicBlock *trueDest,
198 BasicBlock *falseDest) {
199 return insertTerminator(
200 CondBranchInst::create(condition, trueDest, falseDest));
201 }
202
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700203private:
204 template <typename T>
205 T *insertTerminator(T *term) {
206 block->setTerminator(term);
207 return term;
208 }
209
210 CFGFunction *function;
211 BasicBlock *block = nullptr;
212 BasicBlock::iterator insertPoint;
213};
214
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700215/// This class helps build an MLFunction. Statements that are created are
216/// automatically inserted at an insertion point or added to the current
217/// statement block.
218class MLFuncBuilder : public Builder {
219public:
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700220 /// Create ML function builder and set insertion point to the given
221 /// statement block, that is, given ML function, for statement or if statement
222 /// clause.
223 MLFuncBuilder(StmtBlock *block)
224 : Builder(block->findFunction()->getContext()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700225 setInsertionPoint(block);
226 }
227
228 /// Reset the insertion point to no location. Creating an operation without a
229 /// set insertion point is an error, but this can still be useful when the
230 /// current insertion point a builder refers to is being removed.
231 void clearInsertionPoint() {
232 this->block = nullptr;
233 insertPoint = StmtBlock::iterator();
234 }
235
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700236 /// Set the insertion point to the specified location.
237 /// Unlike CFGFuncBuilder, MLFuncBuilder allows to set insertion
238 /// point to a different function.
239 void setInsertionPoint(StmtBlock *block, StmtBlock::iterator insertPoint) {
240 // TODO: check that insertPoint is in this rather than some other block.
241 this->block = block;
242 this->insertPoint = insertPoint;
243 }
244
245 /// Set the insertion point to the specified operation.
246 void setInsertionPoint(OperationStmt *stmt) {
247 setInsertionPoint(stmt->getBlock(), StmtBlock::iterator(stmt));
248 }
249
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700250 /// Set the insertion point to the end of the specified block.
251 void setInsertionPoint(StmtBlock *block) {
252 this->block = block;
253 insertPoint = block->end();
254 }
255
Uday Bondhugula15984952018-08-01 22:36:12 -0700256 /// Set the insertion point at the beginning of the specified block.
257 void setInsertionPointAtStart(StmtBlock *block) {
258 this->block = block;
259 insertPoint = block->begin();
260 }
261
Uday Bondhugula84b80952018-08-03 13:22:26 -0700262 /// Get the current insertion point of the builder.
263 StmtBlock::iterator getInsertionPoint() const { return insertPoint; }
264
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700265 // TODO(clattner): remove this.
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700266 OperationStmt *createOperation(Identifier name, ArrayRef<MLValue *> operands,
267 ArrayRef<Type *> resultTypes,
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700268 ArrayRef<NamedAttribute> attributes) {
Uday Bondhugula9f7754e2018-07-31 14:26:07 -0700269 auto *op =
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700270 OperationStmt::create(name, operands, resultTypes, attributes, context);
Uday Bondhugula9f7754e2018-07-31 14:26:07 -0700271 block->getStatements().insert(insertPoint, op);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700272 return op;
273 }
274
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700275 /// Create an operation given the fields represented as an OperationState.
276 OperationStmt *createOperation(const OperationState &state);
277
278 // TODO(clattner): rework build to return an OperationState so the
279 // implementations can moved out of line.
Jacques Pienaarac86d102018-08-03 08:16:37 -0700280 // Create operation of specific op type at the current insertion point.
281 template <typename OpTy, typename... Args>
282 OpPointer<OpTy> create(Args... args) {
283 return OpTy::build(this, args...);
284 }
285
Uday Bondhugula84b80952018-08-03 13:22:26 -0700286 Statement *clone(const Statement &stmt) {
Uday Bondhugula134154e2018-08-06 18:40:34 -0700287 Statement *cloneStmt = stmt.clone();
288 block->getStatements().insert(insertPoint, cloneStmt);
289 return cloneStmt;
Uday Bondhugula84b80952018-08-03 13:22:26 -0700290 }
291
Chris Lattner1604e472018-07-23 08:42:19 -0700292 // Creates for statement. When step is not specified, it is set to 1.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -0700293 ForStmt *createFor(AffineConstantExpr *lowerBound,
294 AffineConstantExpr *upperBound,
295 AffineConstantExpr *step = nullptr);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700296
297 IfStmt *createIf() {
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700298 auto *stmt = new IfStmt();
299 block->getStatements().insert(insertPoint, stmt);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700300 return stmt;
301 }
302
303private:
304 StmtBlock *block = nullptr;
305 StmtBlock::iterator insertPoint;
306};
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700307
308} // namespace mlir
309
310#endif