blob: 4e9a5c86253d7be5c7b8c2613c6d285f3a60028b [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;
Chris Lattnerfc647d52018-08-27 21:05:16 -070028class UnknownLoc;
29class UniquedFilename;
30class FileLineColLoc;
Chris Lattner158e0a3e2018-07-08 20:51:38 -070031class Type;
32class PrimitiveType;
33class IntegerType;
34class FunctionType;
35class VectorType;
36class RankedTensorType;
37class UnrankedTensorType;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070038class BoolAttr;
39class IntegerAttr;
40class FloatAttr;
41class StringAttr;
James Molloyf0d2f442018-08-03 01:54:46 -070042class TypeAttr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070043class ArrayAttr;
Chris Lattner4613d9e2018-08-19 21:17:22 -070044class FunctionAttr;
MLIR Teamb61885d2018-07-18 16:29:21 -070045class AffineMapAttr;
Chris Lattner1ac20cb2018-07-10 10:59:53 -070046class AffineMap;
47class AffineExpr;
48class AffineConstantExpr;
49class AffineDimExpr;
50class AffineSymbolExpr;
Chris Lattner158e0a3e2018-07-08 20:51:38 -070051
52/// This class is a general helper class for creating context-global objects
53/// like types, attributes, and affine expressions.
54class Builder {
55public:
56 explicit Builder(MLIRContext *context) : context(context) {}
57 explicit Builder(Module *module);
58
59 MLIRContext *getContext() const { return context; }
60
Chris Lattner1ac20cb2018-07-10 10:59:53 -070061 Identifier getIdentifier(StringRef str);
62 Module *createModule();
63
Chris Lattnerfc647d52018-08-27 21:05:16 -070064 // Locations.
65 UnknownLoc *getUnknownLoc();
66 UniquedFilename getUniquedFilename(StringRef filename);
67 FileLineColLoc *getFileLineColLoc(UniquedFilename filename, unsigned line,
68 unsigned column);
69
Chris Lattner158e0a3e2018-07-08 20:51:38 -070070 // Types.
Chris Lattnerc3251192018-07-27 13:09:58 -070071 FloatType *getBF16Type();
72 FloatType *getF16Type();
73 FloatType *getF32Type();
74 FloatType *getF64Type();
75
76 OtherType *getAffineIntType();
77 OtherType *getTFControlType();
James Molloy72b0cbe2018-08-01 12:55:27 -070078 OtherType *getTFStringType();
Chris Lattner158e0a3e2018-07-08 20:51:38 -070079 IntegerType *getIntegerType(unsigned width);
80 FunctionType *getFunctionType(ArrayRef<Type *> inputs,
81 ArrayRef<Type *> results);
Jacques Pienaarc03c6952018-08-10 11:56:47 -070082 MemRefType *getMemRefType(ArrayRef<int> shape, Type *elementType,
83 ArrayRef<AffineMap *> affineMapComposition = {},
84 unsigned memorySpace = 0);
Chris Lattner158e0a3e2018-07-08 20:51:38 -070085 VectorType *getVectorType(ArrayRef<unsigned> shape, Type *elementType);
86 RankedTensorType *getTensorType(ArrayRef<int> shape, Type *elementType);
87 UnrankedTensorType *getTensorType(Type *elementType);
88
Chris Lattner1ac20cb2018-07-10 10:59:53 -070089 // Attributes.
90 BoolAttr *getBoolAttr(bool value);
91 IntegerAttr *getIntegerAttr(int64_t value);
92 FloatAttr *getFloatAttr(double value);
93 StringAttr *getStringAttr(StringRef bytes);
94 ArrayAttr *getArrayAttr(ArrayRef<Attribute *> value);
MLIR Teamb61885d2018-07-18 16:29:21 -070095 AffineMapAttr *getAffineMapAttr(AffineMap *value);
James Molloyf0d2f442018-08-03 01:54:46 -070096 TypeAttr *getTypeAttr(Type *type);
Chris Lattner1aa46322018-08-21 17:55:22 -070097 FunctionAttr *getFunctionAttr(const Function *value);
Chris Lattner1ac20cb2018-07-10 10:59:53 -070098
Uday Bondhugula4266fc72018-09-13 08:12:38 -070099 // Affine expressions and affine maps.
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700100 AffineDimExpr *getDimExpr(unsigned position);
101 AffineSymbolExpr *getSymbolExpr(unsigned position);
102 AffineConstantExpr *getConstantExpr(int64_t constant);
103 AffineExpr *getAddExpr(AffineExpr *lhs, AffineExpr *rhs);
104 AffineExpr *getSubExpr(AffineExpr *lhs, AffineExpr *rhs);
105 AffineExpr *getMulExpr(AffineExpr *lhs, AffineExpr *rhs);
Uday Bondhugulacf4f4c42018-09-12 10:21:23 -0700106 AffineExpr *getMulExpr(AffineExpr *lhs, int64_t rhs);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700107 AffineExpr *getModExpr(AffineExpr *lhs, AffineExpr *rhs);
Uday Bondhugulacf4f4c42018-09-12 10:21:23 -0700108 AffineExpr *getModExpr(AffineExpr *lhs, uint64_t rhs);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700109 AffineExpr *getFloorDivExpr(AffineExpr *lhs, AffineExpr *rhs);
Uday Bondhugulacf4f4c42018-09-12 10:21:23 -0700110 AffineExpr *getFloorDivExpr(AffineExpr *lhs, uint64_t rhs);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700111 AffineExpr *getCeilDivExpr(AffineExpr *lhs, AffineExpr *rhs);
Uday Bondhugulacf4f4c42018-09-12 10:21:23 -0700112 AffineExpr *getCeilDivExpr(AffineExpr *lhs, uint64_t rhs);
Chris Lattner1ac20cb2018-07-10 10:59:53 -0700113
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700114 /// Creates a sum of products affine expression from constant coefficients.
115 /// If c_0, c_1, ... are the coefficients in the order corresponding to
116 /// dimensions, symbols, and the constant term, create the affine expression:
117 /// expr = c_0*d0 + c_1*d1 + ... + c_{ndims-1}*d_{ndims-1} + c_{..}*s0 +
118 /// c_{..}*s1 + ... + const
119 AffineExpr *getAddMulPureAffineExpr(unsigned numDims, unsigned numSymbols,
120 ArrayRef<int64_t> coeffs);
121
122 AffineMap *getAffineMap(unsigned dimCount, unsigned symbolCount,
123 ArrayRef<AffineExpr *> results,
124 ArrayRef<AffineExpr *> rangeSizes);
Uday Bondhugulabc535622018-08-07 14:24:38 -0700125
Tatiana Shpeismande8829f2018-08-24 23:38:14 -0700126 // Special cases of affine maps and integer sets
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700127 /// Returns a single constant result affine map with 0 dimensions and 0
128 /// symbols. One constant result: () -> (val).
129 AffineMap *getConstantAffineMap(int64_t val);
Tatiana Shpeismande8829f2018-08-24 23:38:14 -0700130 // One dimension id identity map: (i) -> (i).
131 AffineMap *getDimIdentityMap();
132 // One symbol identity map: ()[s] -> (s).
133 AffineMap *getSymbolIdentityMap();
134
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700135 // Integer set.
136 IntegerSet *getIntegerSet(unsigned dimCount, unsigned symbolCount,
137 ArrayRef<AffineExpr *> constraints,
138 ArrayRef<bool> isEq);
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700139 // TODO: Helpers for affine map/exprs, etc.
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700140protected:
141 MLIRContext *context;
142};
143
144/// This class helps build a CFGFunction. Instructions that are created are
145/// automatically inserted at an insertion point or added to the current basic
146/// block.
147class CFGFuncBuilder : public Builder {
148public:
Chris Lattner8174f3a2018-07-29 16:45:23 -0700149 CFGFuncBuilder(BasicBlock *block, BasicBlock::iterator insertPoint)
150 : Builder(block->getFunction()->getContext()),
151 function(block->getFunction()) {
152 setInsertionPoint(block, insertPoint);
153 }
154
155 CFGFuncBuilder(OperationInst *insertBefore)
156 : CFGFuncBuilder(insertBefore->getBlock(),
157 BasicBlock::iterator(insertBefore)) {}
158
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700159 CFGFuncBuilder(BasicBlock *block)
160 : Builder(block->getFunction()->getContext()),
161 function(block->getFunction()) {
162 setInsertionPoint(block);
163 }
Chris Lattner8174f3a2018-07-29 16:45:23 -0700164
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700165 CFGFuncBuilder(CFGFunction *function)
166 : Builder(function->getContext()), function(function) {}
167
168 /// Reset the insertion point to no location. Creating an operation without a
169 /// set insertion point is an error, but this can still be useful when the
170 /// current insertion point a builder refers to is being removed.
171 void clearInsertionPoint() {
172 this->block = nullptr;
173 insertPoint = BasicBlock::iterator();
174 }
175
Chris Lattner8174f3a2018-07-29 16:45:23 -0700176 /// Set the insertion point to the specified location.
177 void setInsertionPoint(BasicBlock *block, BasicBlock::iterator insertPoint) {
178 assert(block->getFunction() == function &&
179 "can't move to a different function");
180 this->block = block;
181 this->insertPoint = insertPoint;
182 }
183
184 /// Set the insertion point to the specified operation.
185 void setInsertionPoint(OperationInst *inst) {
186 setInsertionPoint(inst->getBlock(), BasicBlock::iterator(inst));
187 }
188
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700189 /// Set the insertion point to the end of the specified block.
190 void setInsertionPoint(BasicBlock *block) {
Chris Lattner8174f3a2018-07-29 16:45:23 -0700191 setInsertionPoint(block, block->end());
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700192 }
193
Chris Lattner992a1272018-08-07 12:02:37 -0700194 void insert(OperationInst *opInst) {
195 block->getOperations().insert(insertPoint, opInst);
196 }
197
Chris Lattner8a9310a2018-08-24 21:13:19 -0700198 /// Add new basic block and set the insertion point to the end of it. If an
199 /// 'insertBefore' basic block is passed, the block will be placed before the
200 /// specified block. If not, the block will be appended to the end of the
201 /// current function.
202 BasicBlock *createBlock(BasicBlock *insertBefore = nullptr);
Tatiana Shpeisman6708b452018-07-24 10:15:13 -0700203
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700204 /// Create an operation given the fields represented as an OperationState.
205 OperationInst *createOperation(const OperationState &state);
206
Chris Lattner7879f842018-09-02 22:01:45 -0700207 /// Create operation of specific op type at the current insertion point
208 /// without verifying to see if it is valid.
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700209 template <typename OpTy, typename... Args>
Chris Lattnerfc647d52018-08-27 21:05:16 -0700210 OpPointer<OpTy> create(Location *location, Args... args) {
Chris Lattner1628fa02018-08-23 14:32:25 -0700211 OperationState state(getContext(), location, OpTy::getOperationName());
Chris Lattner1eb77482018-08-22 19:25:49 -0700212 OpTy::build(this, &state, args...);
213 auto *inst = createOperation(state);
Chris Lattner992a1272018-08-07 12:02:37 -0700214 auto result = inst->template getAs<OpTy>();
215 assert(result && "Builder didn't return the right type");
216 return result;
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700217 }
218
Chris Lattner7879f842018-09-02 22:01:45 -0700219 /// Create operation of specific op type at the current insertion point. If
220 /// the result is an invalid op (the verifier hook fails), emit a the
221 /// specified error message and return null.
222 template <typename OpTy, typename... Args>
Chris Lattner015100b2018-09-09 20:40:23 -0700223 OpPointer<OpTy> createChecked(Location *location, Args... args) {
Chris Lattner7879f842018-09-02 22:01:45 -0700224 OperationState state(getContext(), location, OpTy::getOperationName());
225 OpTy::build(this, &state, args...);
226 auto *inst = createOperation(state);
Chris Lattner7879f842018-09-02 22:01:45 -0700227
Chris Lattner015100b2018-09-09 20:40:23 -0700228 // If the OperationInst we produce is valid, return it.
229 if (!OpTy::verifyInvariants(inst)) {
230 auto result = inst->template getAs<OpTy>();
231 assert(result && "Builder didn't return the right type");
Chris Lattner7879f842018-09-02 22:01:45 -0700232 return result;
Chris Lattner015100b2018-09-09 20:40:23 -0700233 }
234
235 // Otherwise, the error message got emitted. Just remove the instruction
236 // we made.
Chris Lattner7879f842018-09-02 22:01:45 -0700237 inst->eraseFromBlock();
238 return OpPointer<OpTy>();
239 }
240
Uday Bondhugula15984952018-08-01 22:36:12 -0700241 OperationInst *cloneOperation(const OperationInst &srcOpInst) {
242 auto *op = srcOpInst.clone();
Chris Lattner992a1272018-08-07 12:02:37 -0700243 insert(op);
Uday Bondhugula15984952018-08-01 22:36:12 -0700244 return op;
245 }
246
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700247 // Terminators.
248
Chris Lattnerfc647d52018-08-27 21:05:16 -0700249 ReturnInst *createReturn(Location *location, ArrayRef<CFGValue *> operands) {
Chris Lattner1628fa02018-08-23 14:32:25 -0700250 return insertTerminator(ReturnInst::create(location, operands));
Chris Lattner40746442018-07-21 14:32:09 -0700251 }
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700252
Chris Lattnerfc647d52018-08-27 21:05:16 -0700253 BranchInst *createBranch(Location *location, BasicBlock *dest,
Chris Lattner8a9310a2018-08-24 21:13:19 -0700254 ArrayRef<CFGValue *> operands = {}) {
255 return insertTerminator(BranchInst::create(location, dest, operands));
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700256 }
257
Chris Lattnerfc647d52018-08-27 21:05:16 -0700258 CondBranchInst *createCondBranch(Location *location, CFGValue *condition,
Chris Lattner091a6b52018-08-23 14:58:27 -0700259 BasicBlock *trueDest,
260 BasicBlock *falseDest) {
James Molloy4f788372018-07-24 15:01:27 -0700261 return insertTerminator(
Chris Lattner1628fa02018-08-23 14:32:25 -0700262 CondBranchInst::create(location, condition, trueDest, falseDest));
James Molloy4f788372018-07-24 15:01:27 -0700263 }
264
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700265private:
266 template <typename T>
267 T *insertTerminator(T *term) {
268 block->setTerminator(term);
269 return term;
270 }
271
272 CFGFunction *function;
273 BasicBlock *block = nullptr;
274 BasicBlock::iterator insertPoint;
275};
276
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700277/// This class helps build an MLFunction. Statements that are created are
278/// automatically inserted at an insertion point or added to the current
279/// statement block.
280class MLFuncBuilder : public Builder {
281public:
Chris Lattnere787b322018-08-08 11:14:57 -0700282 /// Create ML function builder and set insertion point to the given statement,
283 /// which will cause subsequent insertions to go right before it.
284 MLFuncBuilder(Statement *stmt)
285 // TODO: Eliminate findFunction from this.
286 : Builder(stmt->findFunction()->getContext()) {
287 setInsertionPoint(stmt);
288 }
289
290 MLFuncBuilder(StmtBlock *block, StmtBlock::iterator insertPoint)
291 // TODO: Eliminate findFunction from this.
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700292 : Builder(block->findFunction()->getContext()) {
Chris Lattnere787b322018-08-08 11:14:57 -0700293 setInsertionPoint(block, insertPoint);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700294 }
295
296 /// Reset the insertion point to no location. Creating an operation without a
297 /// set insertion point is an error, but this can still be useful when the
298 /// current insertion point a builder refers to is being removed.
299 void clearInsertionPoint() {
300 this->block = nullptr;
301 insertPoint = StmtBlock::iterator();
302 }
303
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700304 /// Set the insertion point to the specified location.
305 /// Unlike CFGFuncBuilder, MLFuncBuilder allows to set insertion
306 /// point to a different function.
307 void setInsertionPoint(StmtBlock *block, StmtBlock::iterator insertPoint) {
308 // TODO: check that insertPoint is in this rather than some other block.
309 this->block = block;
310 this->insertPoint = insertPoint;
311 }
312
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700313 /// Sets the insertion point to the specified operation, which will cause
Uday Bondhugula67701712018-08-21 16:01:23 -0700314 /// subsequent insertions to go right before it.
Chris Lattnere787b322018-08-08 11:14:57 -0700315 void setInsertionPoint(Statement *stmt) {
Tatiana Shpeismand880b352018-07-31 23:14:16 -0700316 setInsertionPoint(stmt->getBlock(), StmtBlock::iterator(stmt));
317 }
318
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700319 /// Sets the insertion point to the start of the specified block.
Chris Lattnere787b322018-08-08 11:14:57 -0700320 void setInsertionPointToStart(StmtBlock *block) {
Tatiana Shpeismande8829f2018-08-24 23:38:14 -0700321 setInsertionPoint(block, block->begin());
Uday Bondhugula15984952018-08-01 22:36:12 -0700322 }
323
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700324 /// Sets the insertion point to the end of the specified block.
Chris Lattnere787b322018-08-08 11:14:57 -0700325 void setInsertionPointToEnd(StmtBlock *block) {
Tatiana Shpeismande8829f2018-08-24 23:38:14 -0700326 setInsertionPoint(block, block->end());
Chris Lattnere787b322018-08-08 11:14:57 -0700327 }
328
Uday Bondhugula84b80952018-08-03 13:22:26 -0700329 /// Get the current insertion point of the builder.
330 StmtBlock::iterator getInsertionPoint() const { return insertPoint; }
331
Chris Lattnereed6c4d2018-08-07 09:12:35 -0700332 /// Create an operation given the fields represented as an OperationState.
333 OperationStmt *createOperation(const OperationState &state);
334
Chris Lattner992a1272018-08-07 12:02:37 -0700335 /// Create operation of specific op type at the current insertion point.
Jacques Pienaarac86d102018-08-03 08:16:37 -0700336 template <typename OpTy, typename... Args>
Chris Lattnerfc647d52018-08-27 21:05:16 -0700337 OpPointer<OpTy> create(Location *location, Args... args) {
Chris Lattner1628fa02018-08-23 14:32:25 -0700338 OperationState state(getContext(), location, OpTy::getOperationName());
Chris Lattner1eb77482018-08-22 19:25:49 -0700339 OpTy::build(this, &state, args...);
340 auto *stmt = createOperation(state);
Chris Lattner992a1272018-08-07 12:02:37 -0700341 auto result = stmt->template getAs<OpTy>();
342 assert(result && "Builder didn't return the right type");
343 return result;
Jacques Pienaarac86d102018-08-03 08:16:37 -0700344 }
345
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700346 /// Creates an operation of specific op type at the current insertion point.
347 /// If the result is an invalid op (the verifier hook fails), emit an error
348 /// and return null.
Chris Lattner7879f842018-09-02 22:01:45 -0700349 template <typename OpTy, typename... Args>
Chris Lattner015100b2018-09-09 20:40:23 -0700350 OpPointer<OpTy> createChecked(Location *location, Args... args) {
Chris Lattner7879f842018-09-02 22:01:45 -0700351 OperationState state(getContext(), location, OpTy::getOperationName());
352 OpTy::build(this, &state, args...);
353 auto *stmt = createOperation(state);
Chris Lattner7879f842018-09-02 22:01:45 -0700354
Chris Lattner015100b2018-09-09 20:40:23 -0700355 // If the OperationStmt we produce is valid, return it.
356 if (!OpTy::verifyInvariants(stmt)) {
357 auto result = stmt->template getAs<OpTy>();
358 assert(result && "Builder didn't return the right type");
Chris Lattner7879f842018-09-02 22:01:45 -0700359 return result;
Chris Lattner015100b2018-09-09 20:40:23 -0700360 }
361
362 // Otherwise, the error message got emitted. Just remove the statement
363 // we made.
Chris Lattner7879f842018-09-02 22:01:45 -0700364 stmt->eraseFromBlock();
365 return OpPointer<OpTy>();
366 }
367
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700368 /// Creates a deep copy of the specified statement, remapping any operands
369 /// that use values outside of the statement using the map that is provided (
Chris Lattnere787b322018-08-08 11:14:57 -0700370 /// leaving them alone if no entry is present). Replaces references to cloned
371 /// sub-statements to the corresponding statement that is copied, and adds
372 /// those mappings to the map.
373 Statement *clone(const Statement &stmt,
374 OperationStmt::OperandMapTy &operandMapping) {
375 Statement *cloneStmt = stmt.clone(operandMapping, getContext());
Uday Bondhugula134154e2018-08-06 18:40:34 -0700376 block->getStatements().insert(insertPoint, cloneStmt);
377 return cloneStmt;
Uday Bondhugula84b80952018-08-03 13:22:26 -0700378 }
379
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700380 // Creates a for statement. When step is not specified, it is set to 1.
Chris Lattnerfc647d52018-08-27 21:05:16 -0700381 ForStmt *createFor(Location *location, ArrayRef<MLValue *> lbOperands,
Tatiana Shpeismande8829f2018-08-24 23:38:14 -0700382 AffineMap *lbMap, ArrayRef<MLValue *> ubOperands,
383 AffineMap *ubMap, int64_t step = 1);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700384
Uday Bondhugula4266fc72018-09-13 08:12:38 -0700385 // Creates a for statement with known (constant) lower and upper bounds.
386 // Default step is 1.
387 ForStmt *createFor(Location *loc, int64_t lb, int64_t ub, int64_t step = 1);
388
389 /// Creates if statement.
Tatiana Shpeismanc6aa35b2018-08-28 15:26:20 -0700390 IfStmt *createIf(Location *location, ArrayRef<MLValue *> operands,
391 IntegerSet *set);
Tatiana Shpeisman565b9642018-07-16 11:47:09 -0700392
393private:
394 StmtBlock *block = nullptr;
395 StmtBlock::iterator insertPoint;
396};
Chris Lattner158e0a3e2018-07-08 20:51:38 -0700397
398} // namespace mlir
399
400#endif