My Project
Builders.h
Go to the documentation of this file.
1 //===- Builders.h - MLIR Declarative Builder Classes ------------*- C++ -*-===//
2 //
3 // Part of the MLIR 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 //
9 // Provides intuitive composable interfaces for building structured MLIR
10 // snippets in a declarative fashion.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_EDSC_BUILDERS_H_
15 #define MLIR_EDSC_BUILDERS_H_
16 
20 #include "mlir/IR/Builders.h"
22 
23 namespace mlir {
24 
25 namespace edsc {
26 
27 struct index_t {
28  explicit index_t(int64_t v) : v(v) {}
29  explicit operator int64_t() { return v; }
30  int64_t v;
31 };
32 
33 class BlockHandle;
34 class CapturableHandle;
35 class NestedBuilder;
36 class ValueHandle;
37 
44 public:
45  ScopedContext(OpBuilder &builder, Location location);
46 
50  ScopedContext(OpBuilder &builder, OpBuilder::InsertPoint newInsertPt,
51  Location location);
52  ~ScopedContext();
53 
54  static MLIRContext *getContext();
55  static OpBuilder &getBuilder();
56  static Location getLocation();
57 
58 private:
61  friend class NestedBuilder;
62 
63  ScopedContext() = delete;
64  ScopedContext(const ScopedContext &) = delete;
65  ScopedContext &operator=(const ScopedContext &) = delete;
66 
67  static ScopedContext *&getCurrentScopedContext();
68 
70  OpBuilder &builder;
72  Optional<OpBuilder::InsertPoint> prevBuilderInsertPoint;
74  Location location;
76  ScopedContext *enclosingScopedContext;
79  NestedBuilder *nestedBuilder;
80 
81  // TODO: Implement scoping of ValueHandles. To do this we need a proper data
82  // structure to hold ValueHandle objects. We can emulate one but there should
83  // already be something available in LLVM for this purpose.
84 };
85 
95 protected:
96  NestedBuilder() = default;
97  NestedBuilder(const NestedBuilder &) = delete;
98  NestedBuilder(NestedBuilder &&other) : bodyScope(other.bodyScope) {
99  other.bodyScope = nullptr;
100  }
101 
102  NestedBuilder &operator=(const NestedBuilder &) = delete;
104  std::swap(bodyScope, other.bodyScope);
105  return *this;
106  }
107 
115  void enter(mlir::Block *block, int prev = 0) {
116  bodyScope = new ScopedContext(
118  OpBuilder::InsertPoint(block, std::prev(block->end(), prev)),
120  bodyScope->nestedBuilder = this;
121  }
122 
125  void exit() {
126  // Reclaim now to exit the scope.
127  bodyScope->nestedBuilder = nullptr;
128  delete bodyScope;
129  bodyScope = nullptr;
130  }
131 
136  assert(!bodyScope &&
137  "Illegal use of NestedBuilder; must have called exit()");
138  }
139 
140 private:
141  ScopedContext *bodyScope = nullptr;
142 };
143 
150 class LoopBuilder : public NestedBuilder {
151 public:
155  static LoopBuilder makeAffine(ValueHandle *iv,
156  ArrayRef<ValueHandle> lbHandles,
157  ArrayRef<ValueHandle> ubHandles, int64_t step);
161  static LoopBuilder makeLoop(ValueHandle *iv, ValueHandle lbHandle,
162  ValueHandle ubHandle, ValueHandle stepHandle);
163  LoopBuilder(const LoopBuilder &) = delete;
164  LoopBuilder(LoopBuilder &&) = default;
165 
166  LoopBuilder &operator=(const LoopBuilder &) = delete;
167  LoopBuilder &operator=(LoopBuilder &&) = default;
168 
172  void operator()(function_ref<void(void)> fun = nullptr);
173 
174 private:
175  LoopBuilder() = default;
176 };
177 
202 public:
203  // This entry point accommodates the fact that AffineForOp implicitly uses
204  // multiple `lbs` and `ubs` with one single `iv` and `step` to encode `max`
205  // and and `min` constraints respectively.
207  ArrayRef<ValueHandle> ubs, int64_t step);
210 
211  void operator()(function_ref<void(void)> fun = nullptr);
212 
213 private:
215 };
216 
221 public:
224  void operator()(std::function<void(void)> fun = nullptr);
225 
226 private:
228 };
229 
230 // This class exists solely to handle the C++ vexing parse case when
231 // trying to enter a Block that has already been constructed.
232 class Append {};
233 
239 class BlockBuilder : public NestedBuilder {
240 public:
244 
253 
257  void operator()(function_ref<void(void)> fun = nullptr);
258 
259 private:
260  BlockBuilder(BlockBuilder &) = delete;
261  BlockBuilder &operator=(BlockBuilder &other) = delete;
262 };
263 
267 protected:
268  CapturableHandle() = default;
269 };
270 
291 public:
293  static ValueHandle null() { return ValueHandle(); }
294 
300  explicit ValueHandle(Type t) : t(t), v(nullptr) {}
301 
306  explicit ValueHandle(Value v) : t(v->getType()), v(v) {}
307 
313  ValueHandle(index_t cst);
314 
316  ValueHandle(const ValueHandle &other) = default;
317 
320  ValueHandle &operator=(const ValueHandle &other);
321 
323  void swap(ValueHandle &other) {
324  if (this == &other)
325  return;
326  std::swap(t, other.t);
327  std::swap(v, other.v);
328  }
329 
331  operator Value() const { return getValue(); }
332  operator bool() const { return hasValue(); }
333 
336  template <typename Op, typename... Args>
337  static ValueHandle create(Args... args);
338 
344  template <typename Op, typename... Args>
345  static ValueHandle create(OperationFolder *folder, Args... args);
346 
348  // TODO: createOrFold when available and move inside of the `create` method.
349  static ValueHandle createComposedAffineApply(AffineMap map,
350  ArrayRef<Value> operands);
351 
353  static ValueHandle create(StringRef name, ArrayRef<ValueHandle> operands,
354  ArrayRef<Type> resultTypes,
355  ArrayRef<NamedAttribute> attributes = {});
356 
357  bool hasValue() const { return v != nullptr; }
358  Value getValue() const {
359  assert(hasValue() && "Unexpected null value;");
360  return v;
361  }
362  bool hasType() const { return t != Type(); }
363  Type getType() const { return t; }
364 
366  if (!v)
367  return nullptr;
368  return v->getDefiningOp();
369  }
370 
371 protected:
372  ValueHandle() : t(), v(nullptr) {}
373 
376 };
377 
386  OperationHandle() : op(nullptr) {}
387  OperationHandle(Operation *op) : op(op) {}
388 
389  OperationHandle(const OperationHandle &) = default;
390  OperationHandle &operator=(const OperationHandle &) = default;
391 
394  template <typename Op, typename... Args>
395  static OperationHandle create(Args... args);
396  template <typename Op, typename... Args> static Op createOp(Args... args);
397 
399  static OperationHandle create(StringRef name, ArrayRef<ValueHandle> operands,
400  ArrayRef<Type> resultTypes,
401  ArrayRef<NamedAttribute> attributes = {});
402 
403  operator Operation *() { return op; }
404  Operation *getOperation() const { return op; }
405 
406 private:
407  Operation *op;
408 };
409 
411 template <typename HandleType> struct CustomOperation {
412  CustomOperation(StringRef name) : name(name) {
413  static_assert(std::is_same<HandleType, ValueHandle>() ||
414  std::is_same<HandleType, OperationHandle>(),
415  "Only CustomOperation<ValueHandle> or "
416  "CustomOperation<OperationHandle> can be constructed.");
417  }
418  HandleType operator()(ArrayRef<ValueHandle> operands = {},
419  ArrayRef<Type> resultTypes = {},
420  ArrayRef<NamedAttribute> attributes = {}) {
421  return HandleType::create(name, operands, resultTypes, attributes);
422  }
423  std::string name;
424 };
425 
432 public:
437  BlockHandle() : block(nullptr) {}
438 
443  BlockHandle(mlir::Block *block) : block(block) {}
444 
447  BlockHandle(const BlockHandle &) = default;
448  BlockHandle &operator=(const BlockHandle &) = default;
449 
451  static BlockHandle create(ArrayRef<Type> argTypes);
452 
453  operator bool() { return block != nullptr; }
454  operator mlir::Block *() { return block; }
455  mlir::Block *getBlock() { return block; }
456 
457 private:
458  mlir::Block *block;
459 };
460 
461 template <typename Op, typename... Args>
464  .create<Op>(ScopedContext::getLocation(), args...)
465  .getOperation());
466 }
467 
468 template <typename Op, typename... Args>
469 Op OperationHandle::createOp(Args... args) {
470  return cast<Op>(
472  .create<Op>(ScopedContext::getLocation(), args...)
473  .getOperation())
474  .getOperation());
475 }
476 
477 template <typename Op, typename... Args>
480  .create<Op>(ScopedContext::getLocation(), args...)
481  .getOperation();
482  if (op->getNumResults() == 1) {
483  return ValueHandle(op->getResult(0));
484  } else if (op->getNumResults() == 0) {
485  if (auto f = dyn_cast<AffineForOp>(op)) {
486  return ValueHandle(f.getInductionVar());
487  }
488  }
489  llvm_unreachable("unsupported operation, use an OperationHandle instead");
490 }
491 
492 template <typename Op, typename... Args>
494  return folder ? ValueHandle(folder->create<Op>(ScopedContext::getBuilder(),
496  args...))
497  : ValueHandle(ScopedContext::getBuilder().create<Op>(
498  ScopedContext::getLocation(), args...));
499 }
500 
501 namespace op {
502 
510 
521 
522 } // namespace op
523 
526 template <typename Container>
529  res.reserve(values.size());
530  for (auto v : values)
531  res.push_back(ValueHandle(v));
532  return res;
533 }
534 
535 } // namespace edsc
536 } // namespace mlir
537 
538 #endif // MLIR_EDSC_BUILDERS_H_
Definition: InferTypeOpInterface.cpp:20
BlockHandle()
Definition: Builders.h:437
Definition: Builders.h:201
Definition: Operation.h:27
~NestedBuilder()
Definition: Builders.h:135
void create(OpBuilder &builder, SmallVectorImpl< Value > &results, Location location, Args &&... args)
Definition: FoldUtils.h:76
Definition: Attributes.h:139
Value getValue() const
Definition: Builders.h:358
ValueHandle operator%(ValueHandle lhs, ValueHandle rhs)
Definition: Builders.cpp:390
Block represents an ordered list of Operations.
Definition: Block.h:21
Definition: Builders.h:431
ValueHandle operator>=(ValueHandle lhs, ValueHandle rhs)
Definition: Builders.cpp:482
static OperationHandle create(Args... args)
Definition: Builders.h:462
Definition: LLVM.h:49
Definition: Builders.h:290
ValueHandle(Type t)
Definition: Builders.h:300
ValueHandle operator^(ValueHandle lhs, ValueHandle rhs)
Operation * getOperation() const
Definition: Builders.h:404
bool operator!=(IntInfty lhs, IntInfty rhs)
Definition: SDBM.h:94
IntInfty operator+(IntInfty lhs, IntInfty rhs)
Definition: SDBM.h:57
CustomOperation(StringRef name)
Definition: Builders.h:412
static ValueHandle null()
A ValueHandle in a null state can never be captured;.
Definition: Builders.h:293
ValueHandle operator!(ValueHandle value)
Definition: Builders.cpp:405
ValueHandle operator &&(ValueHandle lhs, ValueHandle rhs)
Simple wrapper to build a generic operation without successor blocks.
Definition: Builders.h:411
Definition: LLVM.h:40
ValueHandle()
Definition: Builders.h:372
ValueHandle(Value v)
Definition: Builders.h:306
int64_t v
Definition: Builders.h:30
static ValueHandle create(Args... args)
Definition: Builders.h:478
Type getType() const
Definition: Builders.h:363
Definition: Location.h:52
index_t(int64_t v)
Definition: Builders.h:28
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.cpp:548
OperationHandle(Operation *op)
Definition: Builders.h:387
Definition: LLVM.h:37
int64_t floorDiv(int64_t lhs, int64_t rhs)
Definition: MathExtras.h:31
OpTy create(Location location, Args &&... args)
Create an operation of specific op type at the current insertion point.
Definition: Builders.h:294
OperationHandle()
Definition: Builders.h:386
Definition: Builders.h:220
NestedBuilder & operator=(NestedBuilder &&other)
Definition: Builders.h:103
iterator end()
Definition: Block.h:111
int64_t ceilDiv(int64_t lhs, int64_t rhs)
Definition: MathExtras.h:23
auto map(Fn fun, IterType begin, IterType end) -> SmallVector< typename std::result_of< Fn(decltype(*begin))>::type, 8 >
Map with iterators.
Definition: Functional.h:28
bool hasType() const
Definition: Builders.h:362
Definition: Builders.h:94
ValueHandle operator/(ValueHandle lhs, ValueHandle rhs)
Definition: Builders.cpp:383
OpResult getResult(unsigned idx)
Get the &#39;idx&#39;th result of this operation.
Definition: Operation.h:246
Definition: Builders.h:27
ValueHandle operator>(ValueHandle lhs, ValueHandle rhs)
Definition: Builders.cpp:476
bool hasValue() const
Definition: Builders.h:357
static Op createOp(Args... args)
Definition: Builders.h:469
Definition: AffineMap.h:37
void exit()
Definition: Builders.h:125
Definition: Builders.h:232
std::string name
Definition: Builders.h:423
Definition: Builders.h:150
bool operator==(IntInfty lhs, IntInfty rhs)
Definition: SDBM.h:90
Definition: Types.h:84
Definition: Builders.h:385
Definition: Value.h:38
bool operator<(IntInfty lhs, IntInfty rhs)
Definition: SDBM.h:82
Definition: Builders.h:266
Definition: FoldUtils.h:50
ValueHandle operator||(ValueHandle lhs, ValueHandle rhs)
Definition: Builders.cpp:416
Value v
Definition: Builders.h:375
Definition: LLVM.h:35
static Location getLocation()
Definition: Builders.cpp:58
NestedPattern Op(FilterFunctionType filter)
Definition: NestedMatcher.cpp:111
Definition: Builders.h:43
Type t
Definition: Builders.h:374
This class represents a saved insertion point.
Definition: Builders.h:186
Definition: MLIRContext.h:34
void swap(ValueHandle &other)
Provide a swap operator.
Definition: Builders.h:323
Operation * getOperation() const
Definition: Builders.h:365
AffineExpr operator-(int64_t val, AffineExpr expr)
Definition: AffineExpr.h:207
Definition: OpDefinition.h:949
static OpBuilder & getBuilder()
Definition: Builders.cpp:52
void enter(mlir::Block *block, int prev=0)
Definition: Builders.h:115
Definition: Builders.h:239
AffineExpr operator*(int64_t val, AffineExpr expr)
Definition: AffineExpr.h:206
BlockHandle(mlir::Block *block)
Definition: Builders.h:443
Definition: Builders.h:158
NestedBuilder(NestedBuilder &&other)
Definition: Builders.h:98
bool operator<=(IntInfty lhs, IntInfty rhs)
Definition: SDBM.h:86
HandleType operator()(ArrayRef< ValueHandle > operands={}, ArrayRef< Type > resultTypes={}, ArrayRef< NamedAttribute > attributes={})
Definition: Builders.h:418
mlir::Block * getBlock()
Definition: Builders.h:455
SmallVector< ValueHandle, 8 > makeValueHandles(Container values)
Definition: Builders.h:527