blob: 67cc7b83e1bc05c0b12347739849815c56f9af63 [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
21#include "mlir/IR/CFGFunction.h"
Tatiana Shpeisman565b9642018-07-16 11:47:09 -070022#include "mlir/IR/MLFunction.h"
23#include "mlir/IR/Statements.h"
Chris Lattner158e0a3e2018-07-08 20:51:38 -070024
25namespace mlir {
26class MLIRContext;
27class Module;
28class Type;
29class PrimitiveType;
30class IntegerType;
31class FunctionType;
32class VectorType;
33class RankedTensorType;
34class UnrankedTensorType;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070035class BoolAttr;
36class IntegerAttr;
37class FloatAttr;
38class StringAttr;
39class ArrayAttr;
MLIR Teamb61885d2018-07-18 16:29:21 -070040class AffineMapAttr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070041class AffineMap;
42class AffineExpr;
43class AffineConstantExpr;
44class AffineDimExpr;
45class AffineSymbolExpr;
Chris Lattner158e0a3e2018-07-08 20:51:38 -070046
47/// This class is a general helper class for creating context-global objects
48/// like types, attributes, and affine expressions.
49class Builder {
50public:
51 explicit Builder(MLIRContext *context) : context(context) {}
52 explicit Builder(Module *module);
53
54 MLIRContext *getContext() const { return context; }
55
Chris Lattner1ac20cb2018-07-10 10:59:53 -070056 Identifier getIdentifier(StringRef str);
57 Module *createModule();
58
Chris Lattner158e0a3e2018-07-08 20:51:38 -070059 // Types.
Chris Lattnerc3251192018-07-27 13:09:58 -070060 FloatType *getBF16Type();
61 FloatType *getF16Type();
62 FloatType *getF32Type();
63 FloatType *getF64Type();
64
65 OtherType *getAffineIntType();
66 OtherType *getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -070067 OtherType *getTFStringType();
Chris Lattner158e0a3e2018-07-08 20:51:38 -070068 IntegerType *getIntegerType(unsigned width);
69 FunctionType *getFunctionType(ArrayRef<Type *> inputs,
70 ArrayRef<Type *> results);
71 VectorType *getVectorType(ArrayRef<unsigned> shape, Type *elementType);
72 RankedTensorType *getTensorType(ArrayRef<int> shape, Type *elementType);
73 UnrankedTensorType *getTensorType(Type *elementType);
74
Chris Lattner1ac20cb2018-07-10 10:59:53 -070075 // Attributes.
76 BoolAttr *getBoolAttr(bool value);
77 IntegerAttr *getIntegerAttr(int64_t value);
78 FloatAttr *getFloatAttr(double value);
79 StringAttr *getStringAttr(StringRef bytes);
80 ArrayAttr *getArrayAttr(ArrayRef<Attribute *> value);
MLIR Teamb61885d2018-07-18 16:29:21 -070081 AffineMapAttr *getAffineMapAttr(AffineMap *value);
Chris Lattner1ac20cb2018-07-10 10:59:53 -070082
83 // Affine Expressions and Affine Map.
84 AffineMap *getAffineMap(unsigned dimCount, unsigned symbolCount,
Uday Bondhugula0115dbb2018-07-11 21:31:07 -070085 ArrayRef<AffineExpr *> results,
86 ArrayRef<AffineExpr *> rangeSizes);
Chris Lattner1ac20cb2018-07-10 10:59:53 -070087 AffineDimExpr *getDimExpr(unsigned position);
88 AffineSymbolExpr *getSymbolExpr(unsigned position);
89 AffineConstantExpr *getConstantExpr(int64_t constant);
90 AffineExpr *getAddExpr(AffineExpr *lhs, AffineExpr *rhs);
91 AffineExpr *getSubExpr(AffineExpr *lhs, AffineExpr *rhs);
92 AffineExpr *getMulExpr(AffineExpr *lhs, AffineExpr *rhs);
93 AffineExpr *getModExpr(AffineExpr *lhs, AffineExpr *rhs);
94 AffineExpr *getFloorDivExpr(AffineExpr *lhs, AffineExpr *rhs);
95 AffineExpr *getCeilDivExpr(AffineExpr *lhs, AffineExpr *rhs);
96
Chris Lattner158e0a3e2018-07-08 20:51:38 -070097 // TODO: Helpers for affine map/exprs, etc.
Chris Lattner158e0a3e2018-07-08 20:51:38 -070098protected:
99 MLIRContext *context;
100};
101
102/// This class helps build a CFGFunction. Instructions that are created are
103/// automatically inserted at an insertion point or added to the current basic
104/// block.
105class CFGFuncBuilder : public Builder {
106public:
Chris Lattner8174f3a2018-07-29 16:45:23 -0700107 CFGFuncBuilder(BasicBlock *block, BasicBlock::iterator insertPoint)
108 : Builder(block->getFunction()->getContext()),
109 function(block->getFunction()) {
110 setInsertionPoint(block, insertPoint);
111 }
112
113 CFGFuncBuilder(OperationInst *insertBefore)
114 : CFGFuncBuilder(insertBefore->getBlock(),
115 BasicBlock::iterator(insertBefore)) {}
116
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700117 CFGFuncBuilder(BasicBlock *block)
118 : Builder(block->getFunction()->getContext()),
119 function(block->getFunction()) {
120 setInsertionPoint(block);
121 }
Chris Lattner8174f3a2018-07-29 16:45:23 -0700122
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700123 CFGFuncBuilder(CFGFunction *function)
124 : Builder(function->getContext()), function(function) {}
125
126 /// Reset the insertion point to no location. Creating an operation without a
127 /// set insertion point is an error, but this can still be useful when the
128 /// current insertion point a builder refers to is being removed.
129 void clearInsertionPoint() {
130 this->block = nullptr;
131 insertPoint = BasicBlock::iterator();
132 }
133
Chris Lattner8174f3a2018-07-29 16:45:23 -0700134 /// Set the insertion point to the specified location.
135 void setInsertionPoint(BasicBlock *block, BasicBlock::iterator insertPoint) {
136 assert(block->getFunction() == function &&
137 "can't move to a different function");
138 this->block = block;
139 this->insertPoint = insertPoint;
140 }
141
142 /// Set the insertion point to the specified operation.
143 void setInsertionPoint(OperationInst *inst) {
144 setInsertionPoint(inst->getBlock(), BasicBlock::iterator(inst));
145 }
146
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700147 /// Set the insertion point to the end of the specified block.
148 void setInsertionPoint(BasicBlock *block) {
Chris Lattner8174f3a2018-07-29 16:45:23 -0700149 setInsertionPoint(block, block->end());
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700150 }
151
Tatiana Shpeisman6708b452018-07-24 10:15:13 -0700152 // Add new basic block and set the insertion point to the end of it.
153 BasicBlock *createBlock();
154
Chris Lattner8174f3a2018-07-29 16:45:23 -0700155 // Create an operation at the current insertion point.
Chris Lattner3b2ef762018-07-18 15:31:25 -0700156 OperationInst *createOperation(Identifier name, ArrayRef<CFGValue *> operands,
157 ArrayRef<Type *> resultTypes,
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700158 ArrayRef<NamedAttribute> attributes) {
Chris Lattner3b2ef762018-07-18 15:31:25 -0700159 auto op =
160 OperationInst::create(name, operands, resultTypes, attributes, context);
Chris Lattner8174f3a2018-07-29 16:45:23 -0700161 block->getOperations().insert(insertPoint, op);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700162 return op;
163 }
164
165 // Terminators.
166
Chris Lattner40746442018-07-21 14:32:09 -0700167 ReturnInst *createReturnInst(ArrayRef<CFGValue *> operands) {
168 return insertTerminator(ReturnInst::create(operands));
169 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700170
171 BranchInst *createBranchInst(BasicBlock *dest) {
Chris Lattner40746442018-07-21 14:32:09 -0700172 return insertTerminator(BranchInst::create(dest));
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700173 }
174
James Molloy4f788372018-07-24 15:01:27 -0700175 CondBranchInst *createCondBranchInst(CFGValue *condition,
176 BasicBlock *trueDest,
177 BasicBlock *falseDest) {
178 return insertTerminator(
179 CondBranchInst::create(condition, trueDest, falseDest));
180 }
181
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700182private:
183 template <typename T>
184 T *insertTerminator(T *term) {
185 block->setTerminator(term);
186 return term;
187 }
188
189 CFGFunction *function;
190 BasicBlock *block = nullptr;
191 BasicBlock::iterator insertPoint;
192};
193
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700194/// This class helps build an MLFunction. Statements that are created are
195/// automatically inserted at an insertion point or added to the current
196/// statement block.
197class MLFuncBuilder : public Builder {
198public:
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700199 /// Create ML function builder and set insertion point to the given
200 /// statement block, that is, given ML function, for statement or if statement
201 /// clause.
202 MLFuncBuilder(StmtBlock *block)
203 : Builder(block->findFunction()->getContext()) {
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700204 setInsertionPoint(block);
205 }
206
207 /// Reset the insertion point to no location. Creating an operation without a
208 /// set insertion point is an error, but this can still be useful when the
209 /// current insertion point a builder refers to is being removed.
210 void clearInsertionPoint() {
211 this->block = nullptr;
212 insertPoint = StmtBlock::iterator();
213 }
214
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700215 /// Set the insertion point to the specified location.
216 /// Unlike CFGFuncBuilder, MLFuncBuilder allows to set insertion
217 /// point to a different function.
218 void setInsertionPoint(StmtBlock *block, StmtBlock::iterator insertPoint) {
219 // TODO: check that insertPoint is in this rather than some other block.
220 this->block = block;
221 this->insertPoint = insertPoint;
222 }
223
224 /// Set the insertion point to the specified operation.
225 void setInsertionPoint(OperationStmt *stmt) {
226 setInsertionPoint(stmt->getBlock(), StmtBlock::iterator(stmt));
227 }
228
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700229 /// Set the insertion point to the end of the specified block.
230 void setInsertionPoint(StmtBlock *block) {
231 this->block = block;
232 insertPoint = block->end();
233 }
234
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700235 OperationStmt *createOperation(Identifier name, ArrayRef<MLValue *> operands,
236 ArrayRef<Type *> resultTypes,
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700237 ArrayRef<NamedAttribute> attributes) {
Uday Bondhugula9f7754e2018-07-31 14:26:07 -0700238 auto *op =
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -0700239 OperationStmt::create(name, operands, resultTypes, attributes, context);
Uday Bondhugula9f7754e2018-07-31 14:26:07 -0700240 block->getStatements().insert(insertPoint, op);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700241 return op;
242 }
243
Chris Lattner1604e472018-07-23 08:42:19 -0700244 // Creates for statement. When step is not specified, it is set to 1.
Tatiana Shpeisman1da50c42018-07-19 09:52:39 -0700245 ForStmt *createFor(AffineConstantExpr *lowerBound,
246 AffineConstantExpr *upperBound,
247 AffineConstantExpr *step = nullptr);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700248
249 IfStmt *createIf() {
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700250 auto *stmt = new IfStmt();
251 block->getStatements().insert(insertPoint, stmt);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700252 return stmt;
253 }
254
255private:
256 StmtBlock *block = nullptr;
257 StmtBlock::iterator insertPoint;
258};
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700259
260} // namespace mlir
261
262#endif